if (true) {
// TDZ开始
tmp = "abc"; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
效果
PS C:\Users\Admin\Documents\node-learn> node .\7.js
C:\Users\Admin\Documents\node-learn\7.js:3
tmp = "abc"; // ReferenceError
^
ReferenceError: Cannot access 'tmp' before initialization
at Object.<anonymous> (C:\Users\Admin\Documents\node-learn\7.js:3:7)
at Module._compile (node:internal/modules/cjs/loader:1812:14)
at Object..js (node:internal/modules/cjs/loader:1943:10)
at Module.load (node:internal/modules/cjs/loader:1533:32)
at Module._load (node:internal/modules/cjs/loader:1335:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
at node:internal/main/run_main_module:33:47
Node.js v24.14.1
这个案例可以看出,在没有声明之前赋值,会直接抛出 ReferenceError
typeof在暂时性死区下 typeof 将不再是百分百安全的操作
typeof x; // ReferenceError
let x;
//typeof x;
效果
PS C:\Users\Admin\Documents\node-learn> node .\8.js
C:\Users\Admin\Documents\node-learn\8.js:1
typeof x; // ReferenceError
^
ReferenceError: Cannot access 'x' before initialization
at Object.<anonymous> (C:\Users\Admin\Documents\node-learn\8.js:1:1)
at Module._compile (node:internal/modules/cjs/loader:1812:14)
at Object..js (node:internal/modules/cjs/loader:1943:10)
at Module.load (node:internal/modules/cjs/loader:1533:32)oader:1335:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
at node:internal/main/run_main_module:33:47
Node.js v24.14.1
在 let x 之前,都属于 x 的死区
与之相反,代码中如果没有 let x ,就不存在 x 的死区
// typeof x; // ReferenceError
// let x;
typeof x;
效果
PS C:\Users\Admin\Documents\node-learn> node .\8.js
有些死区也比较隐蔽
function bar(x = y, y = 2) {
// 参数默认值形成独立作用域,x 的默认值表达式引用 y
// x 的初始化在 y 之前(参数从左到右求值),此时 y 尚未初始化,处于 TDZ
return [x, y]; // 因报错不会执行到这
} // 函数定义无问题,但调用时会触发 TDZ
bar(); // 调用时,x 尝试取 y 的值,y 在作用域内但未初始化,抛出 ReferenceError
// 报错原因:参数 y 在 x 的右侧,默认值求值时 y 不可访问(死区)
PS C:\Users\Admin\Documents\node-learn> node .\9.js
C:\Users\Admin\Documents\node-learn\9.js:1
function bar(x = y, y = 2) {
^
ReferenceError: Cannot access 'y' before initialization
at bar (C:\Users\Admin\Documents\node-learn\9.js:1:18)
at Object.<anonymous> (C:\Users\Admin\Documents\node-learn\9.js:5:1)
at Module._compile (node:internal/modules/cjs/loader:1812:14)
at Object..js (node:internal/modules/cjs/loader:1943:10)
at Module.load (node:internal/modules/cjs/loader:1533:32)
at Module._load (node:internal/modules/cjs/loader:1335:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
at node:internal/main/run_main_module:33:47
Node.js v24.14.1
正确写法
function bar(x = 2, y = x) {
return [x, y];
}
bar(); // [2, 2]
输出
PS C:\Users\Admin\Documents\node-learn> node .\10.js
如果你想让代码返回 bar() 的值,则把 bar() 改成 console.log(bar()),即
function bar(x = 2, y = x) {
return [x, y];
}
console.log(bar()); // [2, 2]
结果
PS C:\Users\Admin\Documents\node-lear
n> node .\10.js
[ 2, 2 ]
let 与 var行为不同// 不报错
var x = x;
// 报错
let x = x; // 这里把 x 赋值给 x 相当于 x 还没声明就去取 x 的值
// ReferenceError: x is not defined
效果
PS C:\Users\Admin\Documents\node-learn> node .\11.js
C:\Users\Admin\Documents\node-learn\11.js:5
let x = x;
^
SyntaxError: Identifier 'x' has already been declared
at wrapSafe (node:internal/modules/cjs/loader:1743:18)
at Module._compile (node:internal/modules/cjs/loader:1786:20)
at Object..js (node:internal/modules/cjs/loader:1943:10)
at Module.load (node:internal/modules/cjs/loader:1533:32)
at Module._load (node:internal/modules/cjs/loader:1335:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
at node:internal/main/run_main_module:33:47
Node.js v24.14.1
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量