我正在研究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
(铬)
在初始化之前,ReferenceError:无法访问词法声明x
(火狐)
我知道let
不允许x
提升,但由于它之前被引用(意味着从全局作用域自动声明),在这种情况下不应该发生重新声明吗?
已声明
SyntaxError:标识符
x
因此抛出了上面的错误?
我还了解到,在严格模式下,的第一个代码片段将抛出一个ReferenceError,,那么这是否意味着let
将严格模式(所有变量都需要声明)的这一特定规则强制应用于全局作用域?
发布于 2017-01-04 05:39:02
你说得对,这是很奇怪的行为。它给出这些错误的原因是因为它认为您试图将值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
发布于 2017-01-04 03:51:30
你看过MDN上的let
文档了吗?他们用let描述了的时间死区和错误。
ES6确实将let
变量提升到其作用域的顶部。与var
变量不同的是,当使用let
时,在声明变量之前不能访问它。执行此操作将失败,并显示ReferenceError
(也称为让我们暂时进入死区)。
发布于 2017-01-04 04:13:05
正如Konstantin A.Magg解释的那样,这是因为let
变量被提升,并试图在初始化抛出(临时死区)之前引用它们。
如果您不想这样做,可以将代码拆分到不同的脚本中:
<script>
x = 3;
console.log(x); // 3
</script>
<script>
let x = 42;
console.log(x); // 42
</script>
注意:x = 3
将在严格模式下抛出异常。
https://stackoverflow.com/questions/41451181
复制相似问题