繁体   English   中英

'let'是否覆盖全局声明并抛出ReferenceError?

[英]Does 'let' override a global declaration and throws a ReferenceError?

我正在浏览varlet文档示例之间的区别,并测试当调用未声明的变量时,全局作用域自动为它提供声明(这就是为什么以下代码段不会在任何变量中引发错误):

 x = 3; console.log(x); (function() { y=x+39; })() console.log(y); 

但是,当在同一全局范围内赋值后,使用let声明一个变量:

 x=3; let x = 42; console.log(x); 

抛出以下错误之一:

ReferenceError :未定义x (Chromium)

ReferenceError :在初始化之前无法访问词法声明x (Firefox)

我明白let不允许x提升,但是因为它先前被引用(暗示来自全局范围的自动声明)在这种情况下不应该重新声明吗?

SyntaxError :已声明标识符x

因此抛出上面的错误?

我也明白,在严格模式下的第一个片段会抛出的ReferenceError,那么这是否意味着let (所有变量都需要申报)在全球范围内力量的严格模式这种特殊的规则吗?

你必须看看let在文档MDN 他们描述了时间死区和let的错误

ES6确实将let变量提升到其范围的顶部。 不同,以var变量,使用时let被宣布之前,你不能访问变量。 这样做会导致ReferenceError (也就是让我们的临时死区 )失败。

你是对的,这是奇怪的行为。 它给出这些错误的原因是因为它认为你试图将值3分配给let变量而不是全局值。 正如其他人所提到的,这会导致暂停死区问题。

变量是在实例化包含词法环境时创建的,但在评估变量的LexicalBinding之前可能无法以任何方式访问它们

- 来源(ECMAScript第8版)

此代码显示放置代码导致TDZ的位置:

// Accessing `x` here before control flow evaluates the `let x` statement
// would throw a ReferenceError due to TDZ.
// console.log(x);

let x = 42;
// From here on, accessing `x` is perfectly fine!
console.log(x);

您可以看到将let包装在其自己的块块中可以修复它:

x=3;
{
let x = 42;
console.log(x); // 42
}

或者,您可以在window对象上显式定义全局:

window.x=3;

let x = 42;
console.log(x);  // 42

正如Konstantin A. Magg解释的那样,那是因为let变量被提升并尝试在初始化之前引用它们(时间死区)。

如果您不想这样,可以将代码拆分为不同的脚本:

 <script> x = 3; console.log(x); // 3 </script> <script> let x = 42; console.log(x); // 42 </script> 

注意x = 3将以严格模式抛出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM