- let 的「创建」过程被提升了,但是初始化没有提升,不允许重复声明。
- var 的「创建」和「初始化」都被提升了。
- TDZ 暂时死区,就是不能在初始化之前,使用变量。
let x = 'global'
{
console.log(x) // Uncaught ReferenceError: x is not defined
let x = 1
}
console.log(x)
报错了,说x
没有被定义,说明x
指向的是let x = 1
声明的x
,而不是块代码外的x
变量
这就说明了let x = 1
声明提升了,你觉得代码应该是这样的:
let x = 'global'
{
let x
console.log(x) // Uncaught ReferenceError: x is not defined
x = 1
}
因为let x
不像var x
一样,声明提升随便初始化为undefined
,这样理解没毛病,可以接受。但是看到下面这个例子后,我就懵了。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
按我们上面的理解,代码执行应该是这样的:
var tmp = 123;
if (true) {
let tmp;
tmp = 'abc'; // ReferenceError
}
那么为什么会报错呢,其实是我们理解错了。
let tmp
声明确实被提升了,但同时变量tmp
也进入了暂时性死区,直到真的执行到let tmp
时,变量tmp
才被初始化为undefined
,这时候我们才可以使用变量tmp
下面这段代码就很好理解TDZ 暂时死区
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}