将参数传递给setTimeout的闭包

use*_*715 5 javascript jquery closures document-ready internet-explorer-9

我遇到了一个问题,我的应用程序存在于iframe中,而且它是从外部域调用的.当iframe正确加载时,IE9不会触发加载事件,所以我认为我使用setTimeout来调查页面.

无论如何,我想看看我的setTimeout通常需要什么持续时间来完成,所以我希望能够记录setTimeout从我的回调中触发的延迟,但是我不知道如何将该上下文传递给它所以我可以记录下来.

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

我一直在IE9的控制台中获取LOG:undefined.

完成此任务的正确方法是什么?

谢谢

jfr*_*d00 10

当你的函数setTimeout在将来的某个时候被调用时,循环的值i已经增加到它的范围的末尾,for所以console.log(timings[i]);报告undefined.

i在该函数中使用,您需要在函数闭包中捕获它.有几种方法可以做到这一点.我建议使用自执行函数来捕获这样的值i:

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);
  }
};
Run Code Online (Sandbox Code Playgroud)

作为对其工作原理的一点解释:i作为该函数的第一个参数传递给自执行函数.第一个参数被命名index并在每次调用自执行函数时被冻结,因此for循环不会在setTimeout执行回调之前改变它.因此,index在自执行函数内部引用将获得每个setTimeout回调的数组索引的正确值.


Roc*_*mat 10

发生这种情况是因为你不在身边的值关闭ifunc.循环完成后,i是8(timings.length),这在数组中不存在.

你需要做这样的事情:

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]);
  }
};
Run Code Online (Sandbox Code Playgroud)