ES5 只有两种声明变量的方法:var命令和function命令,ES6 添加了let、const、import和class命令。所以,一共有 6 种声明变量的方法。
ES5 之中,顶层对象的属性与全局变量是等价的。ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
var的特殊行为,就很可能导致bug。我们来看一个循环的例子:
for (var i = 0; i < 6; i++) {
console.log(i)
}
// i 在这里依旧可以访问
console.log(i) // 6
for循环完了,已经不再需要变量i,但是它依旧可以被访问。
所以,ES6引入了块级作用域,让变量的生命周期更加可控。
块级声明-let
let声明的变量不存在变量提升/不存在预解析
//var的情况
console.log(foo);//输出undefined
var foo=2;
//let的情况
console.log(bar);//报错ReferenceError
let bar=2;
var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。es6强制开启严格模式,而let变量未声明不能引用,所以会报 Uncaught ReferenceError。
let声明的变量不允许重复(在同一个作用域内)
let不允许在相同作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
if(true){
console.log(flag);//在声明变量之前的这块区域是访问不了这个变量的,给他起了一个特定的称谓,叫暂时性死区(temporal dead zone,简称 TDZ)。
let flag=123;
}
常量声明-const
使用const声明的变量会被认为是常量(constant),意味着它们的值在被设置完成后就不能再被改变,常量声明与let声明一样,都是块级声明。
const num = 12
num = 13 // 报错SyntaxError:num is read-only
const如果是对象的话,可以向对象中添加属性,也可以修改a的属性;json是指向内存地址的一个指针,指针的指向不变,但是那个被json指针所指向的内存地址所存储的内容是可以变化的;
const obj = { name: 'moddx', age: 28 };
obj.age = 26 // 正常
使用 const 命令声明常量,const声明之后必须赋值,否则会编译不通过;
const声明的值为只读,不允许修改;(一旦赋值不可更改)
总结:尽量不使用var,用let代替var,对于赋值之后不会再做修改的就用const。const一般在require一个模块的时候用或者定义一些全局常量。而let是限制了变量的作用域,保证变量不会去污染全局变量。