Passing parameters into a closure for setTimeout

↘锁芯ラ 提交于 2019-12-01 17:47:04

This is happening because you are not closing around the value of i in your func. When the loop is done, i is 8 (timings.length), which doesn't exist in the array.

You need to do something like this:

App.readyIE9 = function() {
  var timings = [1,250,500,750,1000,1500,2000,3000];    
  for(var i = 0; i < timings.length; i++) {
    var func = function(x) {
      return function(){
          if(App.ready_loaded) return;
          console.log(timings[x]);
          App.readyCallBack();
      };
    };
    setTimeout(func(i),timings[i]);
  }
};

When your function gets called by setTimeout sometime in the future, the value of i has already been incremented to the end of it's range by the for loop so console.log(timings[i]); reports undefined.

To use i in that function, you need to capture it in a function closure. There are several ways to do that. I would suggest using a self-executing function to capture the value of i like this:

App.readyIE9 = function() {
  var timings = [1,250,500,750,1000,1500,2000,3000];    
  for(var i = 0; i < timings.length; i++) {
    (function(index) {
        setTimeout(function() {
            if(App.ready_loaded) return;
            console.log(timings[index]);
            App.readyCallBack();
        }, timings[index]);
    })(i);
  }
};

As a bit of explanation for who this works: i is passed to the self-executing function as the first argument to that function. That first argument is named index and gets frozen with each invocation of the self-executing function so the for loop won't cause it to change before the setTimeout callback is executed. So, referencing index inside of the self-executing function will get the correct value of the array index for each setTimeout callback.

This is a usual problem when you work with setTimeout or setInterval callbacks. You should pass the i value to the function:

var timings = [1, 250, 500, 750, 1000, 1500, 2000, 3000],
    func = function(i) {
        return function() {
            console.log(timings[i]);
        };
    };

for (var i = 0, len = timings.length; i < len; i++) {
    setTimeout(func(i), timings[i]);
}

DEMO: http://jsfiddle.net/r56wu8es/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!