ES5 只有两种声明变量的方法: var 命令和 function 命令。 ES6 一共有6种声明变量的方法:新增了 let 、 const 、 import 令和 class 命令。
1、let
ES6新增 let 命令来声明变量。它的用法类似于 var ,但是所声明的变量,只在 let 所在的代码块内有效。
如:
{
let a = 10;
var b = 11;
}
console.log(b); // 11
console.log(a); // Uncaught ReferenceError: a is not defined
上面代码在代码块中,分别用 let 和 var 声明了两个变量,然后在代码块之外调用这两个变量,结果使用 let 的变量报错, var 声明的变量返回了正确的值,这表明,let 声明的变量只在它所在的代码块中有效。
let 的作用域范围特性,可用于修改闭包中提到的例子以达到部分预期结果。
代码修改如下:将for
循环中的变量i
使用let
声明
for(let i = 0; i < 5; i++){
setTimeout(function(){
console.log(new Date(),i, 'B');
},1000);
}
console.log(new Date(),i,'A');
代码运行结果为:
Uncaught ReferenceError: i is not defined
Sun Aug 13 2017 16:00:18 GMT+0800 (中国标准时间) 0 "B"
Sun Aug 13 2017 16:00:18 GMT+0800 (中国标准时间) 1 "B"
Sun Aug 13 2017 16:00:18 GMT+0800 (中国标准时间) 2 "B"
Sun Aug 13 2017 16:00:18 GMT+0800 (中国标准时间) 3 "B"
Sun Aug 13 2017 16:00:18 GMT+0800 (中国标准时间) 4 "B"
可以看到 B 处正常输出0、1、2、3、4,但是 A 处由于作用域范围原因报错。
注意:
(1) let 不存在“变量提升”现象,即变量可以在声明之前使用。let 声明的变量一定要在声明后使用,否则会报错。
(2)“暂时性死区”(temporal dead zone,TDZ)。
只要在块级作用域内存在 let 命令,它所声明的变量就“绑定”这个区域,不在受外界的影响,即在代码块内,使用 let 命令声明变量之前,该值都是不可用的,并且在声明之前都属于该变量的“死区”。
这使得在变量“死区”中使用 typeof 将会报错(ReferenceError)
typeof x; // ReferenceError
let x;
(3) let 不允许在相同作用域内重复声明一个变量。
2、const
const 声明一个只读变量,一旦声明,常量的值就不能改变。并且,const 声明的变量必须初始化,否则会报错。
const 的作用域和 let 相同:只在声明所在的块级作用域内有效;不存在“变量提升”现象;存在“暂时性的死区”;只能在声明的位置后使用;不可重复声明。
注意: const 只保证变量指向的那个内存地址中的内容不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址中,因此等同于变量。但对于复合类型的数据(引用类型,对象、数值等),变量指向的内存地址,保存的是一个指针, const 只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。
如:
const a = [];
console.log(a.length); // 0
a.push('Hello'); // 可执行
console.log(a.length + " " + a); // 1 Hello
a.length = 0; // 可执行
console.log(a.length + " " + a); // 0
a = []; // 报错,Uncaught TypeError: Assignment to constant variable.