使用 for 循环解释 `let` 和块作用域 [英] Explanation of `let` and block scoping with for loops

查看:12
本文介绍了使用 for 循环解释 `let` 和块作用域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I understand that let prevents duplicate declarations which is nice.

let x;
let x; // error!

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

Variables declared with let can also be used in closures which can be expected

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

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

What I have a bit of difficulty grasping is how let applies to loops. This seems to be specific to for loops. Consider the classic problem:

// 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 有效?在我的想象中,即使只有一个块是可见的,for 实际上为每次迭代创建了一个单独的块,并且 let 声明是在该块内完成的......但是有只有一个 let 声明来初始化值.这只是 ES6 的语法糖吗?这是如何工作的?

Why does using let in this context work? In my imagination even though only one block is visible, for actually creates a separate block for each iteration and the let declaration is done inside of that block ... but there is only one let declaration to initialize the value. Is this just syntactic sugar for ES6? How is this working?

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

I understand the differences between var and let and have illustrated them above. I'm particularly interested in understanding why the different declarations result in different output using a for loop.

推荐答案

这只是 ES6 的语法糖吗?

Is this just syntactic sugar for ES6?

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

No, it's more than syntactic sugar. The gory details are buried in §13.6.3.9 CreatePerIterationEnvironment.

这是如何工作的?

如果您在 for 语句中使用该 let 关键字,它会检查绑定的名称,然后

If you use that let keyword in the for statement, it will check what names it does bind and then

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

你的循环语句 for (var i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); desugars to a simple

Your loop statement for (var i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); desugars to a simple

// 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++;
        …

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

while for (let i = 0; i < 10; i++) process.nextTick(_ => console.log(i)); does "desugar" to the much more complicated

// 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++;
          …

这篇关于使用 for 循环解释 `let` 和块作用域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆