javascript - `let` 的解释和带有 for 循环的 block 作用域

标签 javascript ecmascript-6

我知道 let 可以防止重复声明,这很好。

let x;
let x; // error!

let 声明的变量也可以用在可以预期的闭包中

let i = 100;
setTimeout(function () { console.log(i) }, i); // '100' after 100 ms

我有点难以理解的是 let 如何应用于循环。这似乎特定于 for 循环。考虑经典问题:

// prints '10' 10 times
for (var i = 0; i < 10; i++) { process.nextTick(_ => console.log(i)) }
// prints '0' through '9'
for (let i = 0; i < 10; i++) { process.nextTick(_ => console.log(i)) }

为什么在此上下文中使用 let 有效?在我的想象中,即使只有一个 block 是可见的,for 实际上为每次迭代创建一个单独的 block ,并且 let 声明是在该 block 内完成的......但是有只有一个 let 声明来初始化值。这只是 ES6 的语法糖吗?这是如何工作的?

我了解 varlet 之间的区别,并在上面进行了说明。我特别想了解为什么使用 for 循环时不同的声明会导致不同的输出。

最佳答案

Is this just syntactic sugar for ES6?

不,它不仅仅是语法糖。血淋淋的细节隐藏在 §13.6.3.9 CreatePerIterationEnvironment 中.

How is this working?

如果你使用那个 let for 中的关键字语句,它将检查它绑定(bind)的名称,然后

  • 使用这些名称为 a) 初始化表达式 b) 每次迭代创建一个新的词法环境(之前评估增量表达式)
  • 将具有这些名称的所有变量的值从一个环境复制到下一个环境

你的循环语句 for (var i = 0; i < 10; i++) process.nextTick(_ => console.log(i));脱糖到一个简单的

// omitting braces when they don't introduce a block
var i;
i = 0;
if (i < 10)
    process.nextTick(_ => console.log(i))
    i++;
    if (i < 10)
        process.nextTick(_ => console.log(i))
        i++;
        …

同时 for (let i = 0; i < 10; i++) process.nextTick(_ => console.log(i));对更复杂的情况进行“脱糖”

// using braces to explicitly denote block scopes,
// using indentation for control flow
{ let i;
  i = 0;
  __status = {i};
}
{ let {i} = __status;
  if (i < 10)
      process.nextTick(_ => console.log(i))
      __status = {i};
}   { let {i} = __status;
      i++;
      if (i < 10)
          process.nextTick(_ => console.log(i))
          __status = {i};
    }   { let {i} = __status;
          i++;
          …

关于javascript - `let` 的解释和带有 for 循环的 block 作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30899612/

相关文章:

javascript - Node.js 上的 Multer 抛出 { 错误 : Unexpected field. .. }

javascript - Firebase 相关领域人口

javascript - 我如何在这里使用 ES6 代码而不是 for 循环?

javascript - 如何将所有选定的复选框附加到跨度中

javascript - 获取数组中的对象,该对象具有一个属性,该属性是一个包含匹配值的数组

javascript - 在 JavaScript 中独家使用模板文字?

javascript - 使用 ASP.NET CustomValidator 避免重复的错误消息

javascript - Spring MVC CSS 和 JS 未加载

javascript - 使用 AJAX 附加 PHP 代码

javascript - 如何将 Handlebars 中的字符串解析为 html