在我看来,我已经理解了JavaScript范围和提升的基本概念。在这方面,question+answer给了我很多帮助。
尽管最近我遇到过一些事情,但这让我感到有些惊讶。请考虑以下代码:
var a = 1;
if (true) {
console.log(a);
let a = 2;
}
console.log(a);
鉴于我所学到的知识,我希望它能输出undefined
和1
。虽然它会产生Uncaught ReferenceError: a is not defined
。
我的理解是,上面的代码应该等同于(因为let a = 2;
的声明部分应该被提升到最近的封闭块 - 在这种情况下是if
:
var a = 1;
if (true) {
let a;
console.log(a);
a = 2;
}
console.log(a);
顺便说一下,这段代码会产生undefined
和1
,正如我所料。
我的问题是:
let
声明的变量?
Uncaught ReferenceError: a is not defined
?答案 0 :(得分:3)
有一个名为Temporal Dead Zone的句号,会影响使用let
和const
声明的变量。
解释this answer:
时间死区 - 是进入范围和变量之间的一段时间 被声明,无法访问变量。
所以,如果我们在第一个代码片段中标记Temporal Dead Zone,请问:
var a = 1;
if (true) {
/* start of the Temporal Dead Zone */
console.log(a); /* code in the Temporal Dead Zone */
/* last line of the Temporal Dead Zone */
let a = 2; /* end of the Temporal Dead Zone */
}
console.log(a);
当然,documentation也提到了这个(以及其他棘手的案例):
在ECMAScript 2015中,让绑定不受变量提升的约束,这意味着让声明不会移动到当前执行上下文的顶部。在初始化之前引用块中的变量会导致ReferenceError(与使用var声明的变量相反,该变量将具有未定义的值)。变量位于"临时死区"从块的开始直到处理初始化。
上面的摘录后面跟着这段代码:
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
let foo = 2;
}
要明确地解决问题:正如another answer中所述 - 在 let
声明的变量在最近的封闭块内被提升但未初始化。连续导致变量行为,好像它们没有被提升=)