将参数传递给setTimeout的闭包

我遇到了一个问题,我的应用程序存在于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]); } }; 

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

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

谢谢

发生这种情况是因为你没有在你的func关闭i的值。 循环完成后, 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]); } }; 

当你的函数在将来的某个时候被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); } }; 

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

使用setTimeoutsetInterval回调时,这是一个常见问题。 您应该将i值传递给函数:

 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]); } 

演示: http //jsfiddle.net/r56wu8es/