javascript - ReferenceError 带有在外部作用域中声明的 "let"变量

标签 javascript ecmascript-6

<分区>

考虑一下:

'use strict';

{
  let p = 1;
  {
    console.log(p); 
    let p = 2;
  }
}

直觉告诉我们它应该记录“1”(因为 var 在重新声明之前必须保留其旧值)。但是,实际结果是 ReferenceError。这是为什么? (将不胜感激基于标准的解释)。

请注意,我已经在外部作用域中声明了 p,所以它在内部 block 中是已知的。如果您注释掉 p=2 行,一切正常。

作为事后分析,虽然这种行为似乎已记录在案,但它仍然非常违反直觉,请参见。这个 C 代码:

void main() {
  int p = 1;
  {
    printf("%d\n", p); // prints '1'
    int p = 2;
  }
}

还有一个 JS fuckup 特性需要记下!

最佳答案

根据 MDN :

In ECMAScript 2015, let bindings are not subject to Variable Hoisting, which means that let declarations do not move to the top of the current execution context. Referencing the variable in the block before the initialization results in a ReferenceError (contrary to a variable declared with var, which will just have the undefined value). The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.

问题是你的 let p 语句创建了一个新变量,它的作用域是整个代码块。因此 console.log(p) 中的 p;指的是新创建的变量。

提供了一个与您的情况类似的例子:

function test(){
   var foo = 33;
   if (true) {
     let foo = (foo + 55); // ReferenceError
   }
}
test();

Due to lexical scoping, the identifier "foo" inside the expression (foo + 55) evaluates to the if block's foo, and not the overlying variable foo with the value of 33. In that very line, the if block's "foo" has already been created in the lexical environment, but has not yet reached (and terminated) its initialization (which is part of the statement itself): it's still in the temporal dead zone.

关于javascript - ReferenceError 带有在外部作用域中声明的 "let"变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45462557/

相关文章:

javascript - 使用ajax提交表单后表单消失

javascript - 为什么这个变量因功能而异?

javascript - JS : EcmaScript6 how to pass different number of parameters to extended class

javascript - 使用对象作为 ES2015 映射键

javascript - 检查 Jest 中功能组件的状态值

javascript - 按日期排序并进行比较,在 React 中返回错误的顺序

javascript - ES6 - 动态类扩展和instanceof

javascript - PDF 的 <object> 阻止下拉菜单

javascript - 无法根据错误的 if/else 语句返回图标

javascript - ng-show "call method"不起作用