代码之家  ›  专栏  ›  技术社区  ›  Marek

回路和闭合。For和Var

  •  0
  • Marek  · 技术社区  · 8 年前

    我发现了许多解释这个问题的主题,关于如何使用var修复以下代码,比如这一个 http://conceptf1.blogspot.com/2013/11/javascript-closures.html 还是这个 JavaScript closure inside loops – simple practical example .

    但我真的不明白为什么在使用var和let时它不起作用。

    var funcs = [];        
    for (var i = 0; i < 3; i++) {        //  let's create 3 functions
      funcs[i] = function() {            //  and store them in funcs
        console.log("My value: " + i);   //  each should log its value.
      };
    }
    for (var j = 0; j < 3; j++) {
      funcs[j]();                        //  and now let's run each one to see
    }
    // outputs 3 3 3
    

    我真的不知道。。。

    3 回复  |  直到 8 年前
        1
  •  1
  •   Mamun    8 年前

    ES6's let 是块范围,这意味着它内部有自己的范围 {} 像许多其他传统语言一样。但相比之下 var 是代码中的全局变量。

    在第一个 for function 刚刚分配给 func[i] 3次,最终值为3,但未执行。如果您首先在内部执行函数 loop ,您将获得预期的输出,尽管如下所示:

    var funcs = [];
    for (var i = 0; i < 3; i++) {      // let's create 3 functions
      funcs[i] = function() {          // and store them in funcs
        console.log("My value: " + i); // each should log its value.
      };
      funcs[i](); // execution of func
    }

    因此,重要的是函数在哪个上下文中执行。

    现在,到时候 funcs[j]() 第一次在代码中执行, i 的值已为 3 . 如果要记录增量值,必须将其作为参数传递,如下所示:

    var funcs = [];
    for (var i = 0; i < 3; i++) {      // let's create 3 functions
      funcs[i] = function(j) {          // and store them in funcs
        console.log("My value: " + j); // each should log its value.
      };
    }
    for (var j = 0; j < 3; j++) {
      funcs[j](j);                      // and now let's run each one to see
    }
        2
  •  0
  •   Zacol    8 年前

    不同于 let var 在回路范围外吊装。事实上,你的 i 变量始终等于最后一次迭代(在您的示例中为3)。 允许 没有这个问题,因为它没有被吊起。

        3
  •  0
  •   inker    8 年前

    因为 var 是函数作用域(即具有周围函数的作用域),而 let & const 是块范围的-因此在每个块内都有自己的值(不管是什么) if -或 else -块或循环的每次迭代(如您的情况)。块范围变量未在块外部定义。函数作用域变量一直保留到函数结束。

    你的 i 变量是函数范围的,这意味着一旦循环完成,它仍然存在于第一个循环之外;值为 3 . 因此,一旦调用数组函数,就需要 一、 从上部范围(即 3. )&输出它。如果您使用 允许 例如,每次迭代都会得到一个新的绑定;你的 一、 的值将保留初始声明值。

    编辑: 因此,为了输出连续值,需要替换 具有 允许 :

    for (let i = 0; i < 3; i++) {
      funcs[i] = function() {
        // now `i` is bound to the scope & keeps its initial value
        console.log("My value: " + i); 
      };
    }