![](/img/trans.png)
[英]ReferenceError is not throwing when accessing 'let' variable before declaration
[英]Does 'let' override a global declaration and throws a ReferenceError?
我正在浏览var
和let
文档示例之间的区别,并测试当调用未声明的变量时,全局作用域自动为它提供声明(这就是为什么以下代码段不会在任何变量中引发错误):
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之前可能无法以任何方式访问它们
此代码显示放置代码导致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.