我听说在初始化之前访问 let
和 const
值会导致 ReferenceError
,因为 暂时死区。
什么是临时死区,它与作用域和吊装有什么关系,在什么情况下会遇到?
最佳答案
let
和 const
与 var
有两大区别:
- 它们是 block scoped .
- 在声明之前访问
var
的结果是undefined
;在声明之前访问let
或const
会抛出ReferenceError
:
console.log(aVar); // undefined
console.log(aLet); // Causes ReferenceError: Cannot access 'aLet' before initialization
var aVar = 1;
let aLet = 2;
从这些示例中可以看出,let
声明(和 const
,其工作方式相同)可能不是 hoisted ,因为 aLet
在被赋值之前似乎并不存在。
然而,情况并非如此——let
和 const
被提升(如 var
,class
和 function
),但是在进入作用域和被声明到无法访问它们之间有一段时间。 这段时间是时间死区(TDZ)。
当 aLet
被声明,而不是分配时,TDZ 结束:
// console.log(aLet) // Would throw ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10
这个例子表明 let
被提升了:
let x = "outer value";
(function() {
// Start TDZ for x.
console.log(x);
let x = "inner value"; // Declaration ends TDZ for x.
}());
来源:Temporal Dead Zone (TDZ) demystified .
在内部范围内访问 x
仍然会导致 ReferenceError
。如果未提升 let
,它将记录 outer value
。
TDZ 是一件好事,因为它有助于突出错误——在声明之前访问一个值很少是有意的。
TDZ 也适用于默认函数参数。参数从左到右计算,每个参数都在 TDZ 中,直到它被赋值:
// b is in TDZ until its value is assigned.
function testDefaults(a = b, b) { }
testDefaults(undefined, 1); // Throws ReferenceError because the evaluation of a reads b before it has been evaluated.
默认情况下,TDZ 在 babel.js 中未启用转译器。打开“高合规”模式以在 REPL 中使用它.提供 es6.spec.blockScoping
标志以将其与 CLI 一起使用或作为库使用。
推荐进一步阅读:TDZ demystified和 ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth .
关于javascript - 什么是暂时死区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54636506/