var
①变量声明提升:
console.log(a); //不会报错,打印undefined
var a;
//如果重复声明a,也不会报错:
var a;
②可重复定义:
var a = 10;
var a = 20;//重复定义a
console.log(a);//打印20
③全局变量挂载到window:
var a = 10;
console.log(window.a);//打印10
/* 声明一个全局的a,它会挂载到window上去。
window.里边有很多属性和方法,如果用var声明,将不会避免:
你var声明的变量会跟window.中的属性同名而覆盖掉window原有的属性,造成冲突.*/
function test() {
a = 10;//暗示全局变量,也会有挂载的问题
}
④ES5中只有两种作用域,全局作用域和局部(函数)作用域:
var arr = [];
for (var i = 0; i < 10; i++) {
arr[i] = function() {
console.log(i);
}
}
arr[0]();//打印10
arr[5]();//打印10
arr[8]();//打印10
//若要分别打印出0,5,8,可用let解决这个闭包问题
ES6 会较好的解决以上问题
let
①let声明的变量,不会变量声明提升:
console.log(a);//报错!如下
let a = 10;
②let在同一块作用域内不能重复声明变量:
let a = 10;
let a = 20;//重复声明
③不会挂载到window:
let a = 10;
console.log(window.a);//打印undefined
④加强了对作用域的控制
有大括号{ }的时候,就会形成 块级作用域 如if{ },while{ },for(){ }等
{
let a = 10;
}
console.log(a);//会报错,如果{}内使用var声明的,这里就会打印10
let a = 10;
{
console.log(a);//可以访问到外边的,打印10
}
临时死区:
let a = 10;
{
console.log(a);
let a = 20;//这个a在大括号内,形成块级作用域,只能在这个大括号里边使用。
}
只要一个变量使用let声明且在大括号内,即使{}外有同名变量,在{}内也不能用,只能找{}内的这个变量,不能去外边找了。所以还是会报错
例:
let m = 10;
{
console.log(m);//首先就会报错!
let m = 20;
{
console.log(m);//注释掉上边console,这里会打印20
}
}
if (true) {
let a = 10;
console.log(a);//打印10
}
console.log(a);//报错
//如果if内是用var声明的,两处都会打印10
var arr = [];
for (let i = 0; i < 10; i++) {//只把var换为let声明,就可以解决这个闭包问题
arr[i] = function() {
console.log(i);
}
}
arr[0]();//打印0
arr[5]();//打印5
arr[8]();//打印8
const
const 与 let 特点一样,不同的是:let声明的是变量,const声明的是常量,且在声明的时候必须初始化赋值,不能使用null占位!只读,声明后不能再修改,会报错。
const PI = 10;//
PI = 10;//改变值,即使是相同的,也会报错!
存储常量的 空间 里面的值不能发生改变
const 保存的是内存地址,可以给对象或数组添加属性,但是不能重新复写。
即原始值是无法改变的,但如果是一个引用值,只要内存地址不变,对象中的值是可以变化的。(理解原始值和引用值)
const PI = {};
PI.name = 20;