let vs var:for 循环中的作用域

qwe*_*xcj 3 javascript closures for-loop ecmascript-6

有人解释一下这个(var 和 let in for 循环之间的行为差​​异)吗?

  1. 经典面试题(结束语):

    let a = [];
    for (var i=0; i<10; i++) {
        a[i] = function() {
          console.log(i,);
        }
    }
    a[0](); // 10
    a[1](); // 10
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果我们使用让:

    let a = [];
    for (let i=0; i<10; i++) {    // var => let
        a[i] = function() {
        console.log(i);
      }
    }
    
    a[0](); // 1
    a[1](); // 2
    
    Run Code Online (Sandbox Code Playgroud)

是的,我在使用“让”时正常并且符合预期。我想到的第一个想法是 let 不支持关闭。但不,它支持。(随后在 Chrome 上对其进行了测试):

function bb() {
  let b = 1;
  return function() {
    console.log(b);
  }
}
bb()();    // 1, means a closure is created
Run Code Online (Sandbox Code Playgroud)

那么我的第二个解释是:当在 for 循环中使用 let 时。对于每个循环,它会反复创建一个新的 i。我在 chrome 调试器中证明了这一点。

问题是:

如果在 for 循环的每个循环中都创建了 i。怎么一直增加???如果每次都创建它,为什么它不会像我们声明的那样保持为 0?

for (let i=0; .......)
Run Code Online (Sandbox Code Playgroud)

Sha*_*ore 6

根据您的示例,let i每次迭代都会创建“词法声明”的环境。但是,for循环使用前一个环境来创建下一个环境。所以当增量发生时,它从它停止的地方开始。否则使用let声明i将创建一个无限循环(即i总是<10)。

这个怎么运作:

在 for 循环体评估中,'test' 和 'result' 之后的步骤是CreatePerIterationEnvironment(perIterationBindings),它声明一个新环境并将所有绑定初始化为其最后一个已知值:thisIterationEnv.InitializeBinding(bn, lastValue)。完成后,新环境将设置为当前环境,然后“增量”步骤开始。

定义:

InitializeBinding(N,V) 设置环境记录中已经存在但未初始化的绑定的值。字符串值 N 是绑定名称的文本。V 是绑定的值,是任何 ECMAScript 语言类型的值。