【问题标题】:let vs var: scopes in for-loop [duplicate]let vs var:for循环中的范围[重复]
【发布时间】:2016-12-12 13:53:39
【问题描述】:

有人解释一下(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
    
  2. 如果我们使用 let:

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

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

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

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

问题是:

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

for (let i=0; .......)

【问题讨论】:

  • @thefourtheye 感谢您的快速编辑!!!
  • 也许再看看this question
  • 请注意,在for 的括号中使用时,IE 不能正确执行let(但如果在for 的正文中使用let 则正确) .
  • @Wickramaranga 这是一个涵盖大部分方面的好方法。谢谢!
  • @nnnnnn 感谢您指出“让在 IE 中”。我认为它解释了一些东西。这意味着括号与 { ... } 有所不同

标签: javascript for-loop ecmascript-6 closures


【解决方案1】:

第一个,错误(意外)结果只是因为闭包可以访问外部函数变量的更新值(最后闭包中的变量'i'是10);


第二个,使用let 声明变量i 将其标记为block variable,这意味着闭包得到立即的i(如IIFE)。

【讨论】:

    【解决方案2】:

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

    它是如何工作的:

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

    定义:

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

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2020-03-28
      • 2017-08-18
      • 2023-04-02
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 2018-12-28
      相关资源
      最近更新 更多