基本用法

let是ES6中新添加的命令,用来声明变量,用法类似var,但是所声明的变量,只在let命令所在的代码块内有效,如:

1
2
3
4
5
6
for(var i=0;i<1;i++){
var b = 3;
let c = 4;
}
console.log(b); // 输出为:3
console.log(c); // 出错

在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。
这表明,let声明的变量只在它所在的代码块有效。
再如下面的计数器代码:

1
2
3
4
5
6
7
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10

由于var声明的变量在整个作用域中都有用,所以每一次循环,新的i值都会覆盖旧值,导致输出的是最后一轮的i的值,也就是 10 。
如果用循环输出ai,所有的值都是 10 。

1
2
3
4
5
6
7
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6

由于let声明的变量只能在当前的代码块中都有用,所以每一次循环,相当于创建了一个新的变量i,所以每次输出的都是当前代码块中的i 。
如果用循环输出ai,得到的就是当前的 i 。

无变量提升

1
2
3
4
5
console.log(foo); // 输出undefined
console.log(bar); // 报错
var foo = 2;
let bar = 2;

var变量会被提升到代码块的最前面声明,而let不会,输出的时候就会报错。

变量区域绑定

1
2
3
4
5
6
var a = 123;
if (true) {
a = 'abc'; // 报错
let a;
}

上面声明了一个局部变量a,导致后者绑定这个块级作用域,所以在let声明变量前,对a赋值会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)

1
2
3
4
5
6
7
8
9
10
11
if (true) {
// TDZ开始
tmp = 'abc'; // 报错
console.log(tmp); // 报错
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}

不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

1
2
3
4
5
6
7
8
9
// 报错
function () {
var a = 3 ; // 报错
let a = 10; // 报错
let a = 1; // 报错
if(true){
let a = 6 ; // 正确
}
}

全部let变量不属于顶层变量

var变量也是window顶层变量,而let变量不再属于window对象。

1
2
3
4
5
6
var a = 1;
window.a // 1
thiw.a 1
let b = 1;
window.b // undefined

本文地址: http://wsdever.github.io/2016/10/01/20161110/