循环的奇怪闭包行为

时间:2015-07-16 07:27:59

标签: javascript closures

所以我已经在SO上学到了很多关于闭包的知识。

但我仍然找到了一个我无法向自己解释的例子:

       function buildList(list){
            var result = [];
            for(var i = 0; i < list.length; i++) {
                var item = "item: " + list[i] + " i's value: " + i;  //i has the value of 2 here, but why?
                result.push( function(){document.write(item + ", list[i]:" + list[i] + ", i's value in the anonymous function:" + i + "<br>")});
            } //i = 3 here
            return result;
        }

        function testList(){
            var testTheList = buildList([1,2,3]);
            for (var j = 0; j < testTheList.length; j++) {
                testTheList[j]();
            }
        }

        testList();

正如我所期望的那样,当我执行testList()时,我应该是3。

但结果是:

item:3我的值:2,list [i]:未定义,我在匿名函数中的值:3

item:3我的值:2,list [i]:未定义,我在匿名函数中的值:3

item:3我的值:2,list [i]:未定义,我在匿名函数中的值:3

为什么我是var item =&gt; 2和i里面的匿名函数=&gt; 3?正如我所读到的,闭包创建了新的执行环境,但是我不应该为闭包创建相同的值吗?

修改

这不是JavaScript closure inside loops – simple practical example的重复,我不想知道如何创建新的执行环境。

我想知道为什么同一个变量i(循环)的值在同一范围内有所不同?

1 个答案:

答案 0 :(得分:0)

当您将新功能添加到result列表时,它会保留对item变量和i计数器的引用。在buildList函数内的循环期间,您不会创建少量item个变量,但是在buildList函数执行值item结束时,您将覆盖现有变量和i变量看起来像这样:

  • 3
  • &#34; item:3我的价值:2&#34;

list[i]undefined,因为您的列表长度为3,您没有list[3]项。因此,当您在testList中循环调用匿名函数时,它会重新生成与itemi变量完全相同的值。还要在循环中创建匿名函数,这不是最佳做法,我建议您修改buildList函数,如下所示:

&#13;
&#13;
function buildList(list) {
    var index = 0;

    return function () {
        if (index >= list.length) return
        var item = "item: " + list[index] + " i's value: " + index;
        document.body.innerHTML += [
          item, ", list[i]:", list[index], 
          ", i's value in the anonymous function:",
          index, "<br>"
        ].join('')
        index++
    }
}

function testList() {
    var list = [1, 2, 3];
    var testTheList = buildList(list);
    document.body.innerHTML = '';
    for (var j = 0; j < list.length; j++) {
        testTheList();
    }
}

testList();
&#13;
&#13;
&#13;