首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >“let”是否覆盖全局声明并抛出ReferenceError?

“let”是否覆盖全局声明并抛出ReferenceError?
EN

Stack Overflow用户
提问于 2017-01-04 03:44:29
回答 3查看 2.6K关注 0票数 10

我正在研究varlet文档示例之间的差异,并测试当调用一个未声明的变量时,全局范围会自动为它提供一个声明(这就是为什么下面的代码片段不会在任何变量中抛出错误的原因):

代码语言:javascript
复制
x = 3;
console.log(x);

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

但是,当在同一全局作用域中的赋值之后使用let声明一个变量时:

代码语言:javascript
复制
x=3;
let x = 42;
console.log(x);

抛出以下错误之一:

未定义铬ReferenceErrorx (铬)

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

我知道let不允许x提升,但由于它之前被引用(意味着从全局作用域自动声明),在这种情况下不应该发生重新声明吗?

已声明

SyntaxError:标识符x

因此抛出了上面的错误?

我还了解到,在严格模式下,的第一个代码片段将抛出一个ReferenceError,,那么这是否意味着let将严格模式(所有变量都需要声明)的这一特定规则强制应用于全局作用域?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-04 05:39:02

你说得对,这是很奇怪的行为。它给出这些错误的原因是因为它认为您试图将值3赋值给let变量,而不是全局值。正如其他人提到的,这导致了提升的时间死区问题。

变量是在实例化其包含的词法环境时创建的,但在对变量的LexicalBinding求值之前,不能以任何方式访问

下面的代码显示了在何处放置代码会导致TDZ:

代码语言:javascript
复制
// 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包装在它自己的块块中可以修复它:

代码语言:javascript
复制
x=3;
{
let x = 42;
console.log(x); // 42
}

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

代码语言:javascript
复制
window.x=3;

let x = 42;
console.log(x);  // 42
票数 2
EN

Stack Overflow用户

发布于 2017-01-04 03:51:30

你看过MDN上的let文档了吗?他们用let描述了的时间死区和错误。

ES6确实将let变量提升到其作用域的顶部。与var变量不同的是,当使用let时,在声明变量之前不能访问它。执行此操作将失败,并显示ReferenceError (也称为让我们暂时进入死区)。

票数 3
EN

Stack Overflow用户

发布于 2017-01-04 04:13:05

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

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

代码语言:javascript
复制
<script>
x = 3;
console.log(x); // 3
</script>

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

注意:x = 3将在严格模式下抛出异常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41451181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档