定义循环内部的函数,i未定义或不可预测的值

时间:2013-03-21 12:22:29

标签: javascript function loops closures

我很想解释一下(取自javascriptkit.com):

function buildList(list) {
  var result = [];
  for (var i = 0; i < list.length; i++) {
    var item = 'item' + list[i];
    result.push( function() {alert(item + ' ' + list[i])} );
  }
  return result;
}

function testList() {
  var fnlist = buildList([1,2,3]);
  // using j only to help prevent confusion - could use i
  for (var j = 0; j < fnlist.length; j++) {
    fnlist[j]();
  }
}

所以testList()非常简单。 我尝试一步一步地遵循第一个功能,这就是我认为会返回的内容:

项目1 1 项目2 2
项目3 3

我得不到的是result如何以item 3 undefined 3次返回 - 为什么未定义,为什么只有item 3

- 正如我正在努力学习的那样,我不打算让它发挥作用,而是要明白我错过了什么部分,以及为什么它不像我期望的那样出现。

2 个答案:

答案 0 :(得分:4)

有什么问题?

for循环中的函数引用i,但i在每次迭代中都在变化,所以当你调用循环中声明的函数时,它会使用i。最后一个值(3)。

一个简单的闭包将保持索引值不受影响:

for (var i = 0; i < list.length; i++) {
    (function(index){
        var item = 'item' + list[index];  // why ?
        result.push( function() {alert(item + ' ' + list[index])} );    
    })(i);    
}

注意:

如果重新查找列表中的值,为什么需要var item = 'item' + list[index];

根据更改的问题

更新

因为i具有最终值-3,这使得您的代码进入最后的迭代:

// i equals to 2 here
var item = 'item' + list[i]; // gives item3
result.push( function() {alert(item + ' ' + list[i])} );
// now `i` is changed to three so we don't enter the loop.

值:

  • item == "item3"
  • i == 3
  • list[i] == list[3] == undefined

答案 1 :(得分:1)

重要的是要理解buildList返回的数组包含共享相同闭包的3函数。每次关闭该闭包的局部变量时 - 它会影响共享它的所有函数。换句话说,结果中所有函数的iitemlist变量都是相同的。在循环遍历list之后,i的值保持等于3result中的所有函数都为真,因为它们共享对该变量的引用。所以,你问题的答案就是这样:

为什么未定义?

因为list[3] === undefined

为什么item 3

因为上次修改item变量的时间是i 2for已执行其正文(list[2] === 3因此item === 'item 3')< / p>