-1

This is probably an easy question but it's late at night and I can't get my head round this.

here's my code

$(document).ready(function () {

var items = getNumber();

for (var i = 0; i < items.length; i++) {

    var test = items[i].action;
    test();

}

});

function getNumber()
{

var items = [];

for (var i = 0; i < 5; i++) {

    var num = i * 10;

    items.push({ id: i, number: num, action: function () { alert(i) } });
}


return items
}

Could someone explain to me why the alert output is always 5? I want the alert parameter to be the index at the time it is added to the array. It seems like it is being dynamic.

If you could also post a solution how i could get this to work i would be extremely thankful

4

1 回答 1

4

这是 JavaScript 变量作用域的一个常见问题:新变量在新的执行上下文中引入,因此在有问题的代码中,在所有操作回调i中共享。

无论如何,这是遵循标准习语的更正代码:

function getNumber()
{
  var items = [];
  for (var i = 0; i < 5; i++) {
    var num = i * 10;    
    items.push({
      id: i, number: num,
      // _i is a new variable for each callback
      action: (function (_i) {
        // use separate (one per callback) _i variable
        return function () { alert(_i) }
      })(i) // pass in current value for loop
    });
  }
  return items
}

或者,如果一个人不喜欢所有的嵌套,可以使用“命名”函数来执行相同的任务。关键是要创建闭包(并从新的执行上下文返回) ,以便关闭不同的变量:

function getNumber()
{
  function mkAction (i) {
      return function () { alert(i) }
  }
  var items = [];
  for (var i = 0; i < 5; i++) {
    var num = i * 10;    
    items.push({
      id: i, number: num,
      action: mkAction(i)
    });
  }
  return items
}

另一种方法是使用Function.bindES5:

function getNumber()
{
  var items = [];
  for (var i = 0; i < 5; i++) {
    var num = i * 10;    
    items.push({
      id: i, number: num,
      action: (function (_i) { alert(_i) }).bind(null, i)
    });
  }
  return items
}

(请注意,即使没有本机浏览器支持,也可以使用新的执行上下文/闭包来模拟 Function.bind。请参阅 MDC 文档。)

也可以看看:

于 2013-09-03T22:19:30.643 回答