将参数传递给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
回调的数组索引的正确值。
使用setTimeout
或setInterval
回调时,这是一个常见问题。 您应该将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/