我遇到了一个问题,我的应用程序位于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:
实现这个目标的正确方法是什么?
由于
答案 0 :(得分:10)
当你的函数在将来的某个时间被setTimeout
调用时,i
的值已经for
循环增加到它的范围的末尾,所以{{1} }报告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
回调的数组索引的正确值。
答案 1 :(得分:10)
这种情况正在发生,因为您没有在i
中缩小func
的价值。循环完成后,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]);
}
};
答案 2 :(得分:3)
使用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]);
}