代码之家  ›  专栏  ›  技术社区  ›  badp

javascript关闭错误时间“存储”值

  •  6
  • badp  · 技术社区  · 15 年前

    我正设法使计数器逐渐增加。以下工作:

    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 回复  |  直到 15 年前
        1
  •  10
  •   Nikita Rybak    15 年前

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

    (function(current_diff) {
        setTimeout(function() {_change_score_by(current_diff);},
                   step * 25);
    })(diff);
    
        2
  •  3
  •   Community Mohan Dere    8 年前

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

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

    你可以 hack this feature 到目前还不支持它的浏览器中获取好处。

        3
  •  2
  •   Community Mohan Dere    8 年前

    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++;
      }
    }