Javascript:如果块被挂起(或不挂起)怎么放?

时间:2017-12-01 08:49:48

标签: javascript scope ecmascript-6 var let

在我看来,我已经理解了JavaScript范围和提升的基本概念。在这方面,question+answer给了我很多帮助。

尽管最近我遇到过一些事情,但这让我感到有些惊讶。请考虑以下代码:

var a = 1;

if (true) {
  console.log(a);
  let a = 2;
}

console.log(a);

鉴于我所学到的知识,我希望它能输出undefined1。虽然它会产生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);

顺便说一下,这段代码会产生undefined1,正如我所料。

我的问题是:

  • 是否在最近的封闭区内提升了let声明的变量?
    • 如果是,为什么第一个块中的代码会产生Uncaught ReferenceError: a is not defined

1 个答案:

答案 0 :(得分:3)

有一个名为Temporal Dead Zone的句号,会影响使用letconst声明的变量。

解释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声明的变量在最近的封闭块内被提升但未初始化。连续导致变量行为,好像它们没有被提升=)