【问题标题】:ES6 javascript block scope variable hoisting into for headerES6 javascript块范围变量提升到标头
【发布时间】:2017-07-07 19:12:31
【问题描述】:

for 循环块中的所有块范围变量是否都被提升到循环头本身之上?

    var x = 4;

    for(let i = 3; i < x; i++) {
        let x = 2;
        ...
    }

每次将 i 与循环头中的 x 进行比较时,是否会在 x 上产生死区错误?我知道 i 在块范围内被下推,但为什么不是 x?

【问题讨论】:

  • 你想达到什么目的?
  • 我正在将块范围的变量添加到我的 javascript 数据库解释器中,我需要知道如何正确处理这种情况。但是,我认为正确的方法是将循环块视为嵌套在循环头中。这样,标头中的let i 在循环块中可见,但循环块中的let x 在循环标头中不可见。
  • 不确定是什么问题?如果var x = 4 是在for 循环之外定义的,为什么还要在for 循环中定义let x = 2
  • 我的问题是i 是循环块范围的一部分,但我应该在哪个范围内搜索x?如果ix 都在同一个范围内,我应该得到一个死区错误——例如如果块范围提升继续通过循环标头来获取标头的let i 声明,并且它也将具有循环的let x 声明。因此,标题中 x 的死区。
  • 问题let i = 3let x = 2 中的示例只能在for 循环中访问。这就是使用let 的目的,是吗?

标签: javascript ecmascript-6 hoisting


【解决方案1】:

语言规范的相关部分是13.7.4

如果for 语句包含letconst 声明,则创建范围。

如果for 语句包含let 声明,则每次迭代都会创建一个范围。

如果 for 主体是块,则创建范围。

以下是一些示例和创建的范围:

//no scope
for(i = 0; i<3; i++) console.log(i);

//no scope
for(var i = 0; i<3; i++) console.log(i);

//for scope and iteration scope
for(let i = 0; i<3; i++) console.log(i);


// for scope, iteration scope and block scope
for(let i = 0; i<3; i++) {
  console.log(i);
}

为什么我们需要迭代范围?对于闭包:

for(let i = 0; i<3; i++) {
  setTimeout(() => console.log(i), 10);
}

没有迭代范围的输出:3,3,3。迭代范围:0,1,2

【讨论】:

  • 感谢您指出相关的 ECMA 标准部分。正如我推测的那样,它是创建嵌套范围,一个用于任何循环标头let,然后如果需要,第二个嵌套范围,一个用于循环主体中的任何let
【解决方案2】:

我误会了,以为只有一个块作用域。我不愿意在表达式i &lt; x 中获取两个任意变量,并且不得不决定在哪个块范围内查找它们,这是不可能确定的。

正确的做法是构建两个嵌套的块作用域,一个用于循环头,一个用于循环体。这意味着let i 在循环头和循环体范围内都可见,而循环中的let x 仅在循环体范围内可见。简单的豌豆,柠檬汁。

【讨论】:

  • “正确的做法是构建两个嵌套的块作用域” for 语句不是块,for 主体不必是一个。所以例如for (let i = 0; i&lt;10; i++) console.log(i); 只创建一个作用域,它不是块作用域。
  • 对,这正是我所说的:循环头创建了一个包含let i = 0; 的范围,在您的情况下,不会有嵌套的循环主体范围。但是当循环体是一个块时,会为其创建一个块作用域,嵌套在循环头作用域内。
【解决方案3】:

for 循环块中的所有块范围变量是否都提升到循环头本身之上?

不,它们是在块范围内提升的

每次将 i 与循环头中的 x 进行比较时,是否会在 x 上产生死区错误?我知道 i 在块范围内被下推,但为什么不是 x?

不,因为循环头中的 x 引用了定义为 4 var x = 4x

在声明let 变量之前,您无法访问它,因为作用域和声明之间的时间是 TDZ。

例如。

console.log(x) // Reference Error, x is in TDZ
let x = 4
console.log(x) // --> 4

【讨论】:

    【解决方案4】:

    基于此,我认为 let x 仅在该范围内可用。

    【讨论】:

      猜你喜欢
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      • 2014-01-20
      • 2023-03-20
      相关资源
      最近更新 更多