Javascript关闭在错误的时间“存储”值

时间:2010-10-17 15:00:43

标签: javascript closures

我正试图逐渐增加反击。以下作品:

function _award(points){    
  var step = 1;
  while(points){
    var diff = Math.ceil(points / 10);
    setTimeout( "_change_score_by("+diff+");" /* sigh */,
                step * 25);
    points -= diff;
    step++;
  }
}

但是,它使用隐式eval。邪恶!让我们使用一个闭包,对吗?

function _award(points){    
  var step = 1;
  while(points){
    var diff = Math.ceil(points / 10);
    setTimeout( function(){ _change_score_by(diff); },
                step * 25);
    points -= diff;
    step++;
  }
}

显然,这不起作用。创建的所有闭包捕获函数中的最后一个值diff - 1.因此,所有匿名函数都会将计数器增加1,例如,_award(100)会将得分增加28。

我该如何正确地做到这一点?

3 个答案:

答案 0 :(得分:10)

这是一个已知问题。但是你可以在每次循环迭代时轻松创建一个闭包:

(function(current_diff) {
    setTimeout(function() {_change_score_by(current_diff);},
               step * 25);
})(diff);

答案 1 :(得分:3)

使用ECMAScript第五版Function#bind方法解决闭包循环问题变得不那么混乱:

setTimeout(_change_score_by.bind(window, diff), step*25);

您可以hack this feature进入不支持它的浏览器,以便立即获得好处。

答案 2 :(得分:2)

Nikita's approach有效(谢谢!),但我个人更喜欢将其更改为更明确的方式:

function _schedule_score_change(diff, step){
  setTimeout( function(){ _change_score_by(diff) },
              step*25 );
}

function _award(points){    
  var step = 1;
  while(points){
    var diff = Math.ceil(points / 10);
    _schedule_score_change(diff, step);
    points -= diff;
    step++;
  }
}