在循环中使用相同的变量来解决“循环中的闭包”问题

时间:2017-01-29 11:34:01

标签: javascript for-loop scope closures

继续this问题,我尝试了以下代码,在两个循环中使用相同的变量,我得到了所需的结果。我的问题是,为什么?

所以初始代码为:

 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]();                      // this will not give desired output
 }

输出结果:

  • 我的价值:3
  • 我的价值:3
  • 我的价值:3

然而,预期的输出是:

  • 我的价值:0
  • 我的价值:1
  • 我的价值:2

现在,如果我在第二个循环中使用变量'i'(全局变量),代码如下:

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 ( i = 0; i < 3; i++) {
  funcs[i]();                      // this gives desired output
}

我得到了预期的输出

  • 我的价值:0
  • 我的价值:1
  • 我的价值:2

为什么?

2 个答案:

答案 0 :(得分:2)

  

现在,如果我在第二个循环中使用变量'i'(全局变量)   好吧......我得到了预期的输出......为什么?

因为当您执行第一个执行循环时:

for (var j = 0; j < 3; j++) {
  funcs[j]();                      
 }

构造数组的循环已经完成,全局变量i的值为3,因此console.log(i)会导致3在每次迭代时都记录for ( i = 0; i < 3; i++) { funcs[i](); } 首先执行循环。当你执行第二个执行循环时:

i

循环的每次迭代都会为全局变量console.log(i)分配一个新值,而let将记录到控制台的这个新值:0,1,2。

您如何以简单的方式达到预期的结果?

您可以使用"use strict"; // use of let requires strict mode var funcs = []; for (let i = 0; i < 3; i++) { // just replace var with let here funcs[i] = function() { console.log("My value: " + i); }; } for (var j = 0; j < 3; j++) { funcs[j](); } 以简单的方式获得所需的结果:

i

现在,数组将使用可访问局部变量的函数构造,在将函数添加到数组时,该变量被赋值为function loop(arr){ arr.forEach(function(element) { enemy = new SuperSmash.Enemy(this.game, element.x, element.y, 'enemy', +element.properties.velocity, this.map, this.player); this.enemies.add(enemy); }, this); }

答案 1 :(得分:1)

因为变量i被污染了。在你的片段中,循环写入相同的变量i,函数读取它。请注意,代码中只有一个变量i

你真正需要获得预期结果的是“模块模式”,它包含一个函数来保持循环中变量的本地副本:

for (var i=0; i<3; i++) {
    (function (j) {
        funcs[j] = function() {          // and store them in funcs
            console.log("My value: " + j); // each should log its value.
        };
    })(i);
}

您可以阅读this article以获取有关“模块模式”的更多信息。