- 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
}