这个应该很容易,但我的脑袋现在似乎已经疲惫不堪了。
我的目标是0,1,2,0,1,2
我的代码到目前为止.... here是一个小提琴。
function delayedLoad(page){
console.log(page);
};
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
setTimeout(function(){
delayedLoad(i);
},3000*i);
}
};
$(document).ready(function(){
// Load the content for the first time.
loadContent();
});
答案 0 :(得分:3)
这是人们遇到的一个非常普遍的问题。
麻烦的是,您在每次迭代中传递给setTimeout
的函数都引用了相同的 i
变量。
JavaScript没有块范围,只有函数范围。因此,要创建一个保留所需i
值的新作用域,需要在循环内调用一个函数,并将其传递给i
。
示例: http://jsfiddle.net/GNwhR/3/
function set_up_timeout( j ) {
setTimeout(function(){
delayedLoad( j );
},3000*j);
}
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
set_up_timeout( i );
}
};
这将您的setTimeout
调用放入另一个函数中,该函数在每次迭代中被调用并传递i
。这将创建一个新的变量范围,其中函数中的j
引用正确的值。
另一种方法是让调用函数返回一个函数:
示例: http://jsfiddle.net/GNwhR/4/
function set_up_callback( j ) {
return function(){
delayedLoad( j );
};
}
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
setTimeout( set_up_callback( i ), 3000*i );
}
};
这一个调用set_up_callback
,返回一个引用j
的函数。
最后,另一种常见的方法是使用IIFE (立即调用函数表达式)来消除命名函数。这不太清楚IMO:
示例: http://jsfiddle.net/GNwhR/5/
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
setTimeout((function( j ){
return function() {
delayedLoad( j );
};
})( i ),3000*i);
}
};
这与前一个示例基本相同,因为它返回一个函数。主要区别在于返回函数的函数是在循环内部创建和调用的。
所有这些都说明了相同的概念,如果您希望稍后异步引用它并使其保持其预期值,则需要对变量进行范围调整。
答案 1 :(得分:1)
function delayedLoad(page){
console.log(page);
};
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log('in loop', i);
setTimeout($.proxy(function(){
delayedLoad(this.page);
}, {page: i}),3000*i);
}
};
$(document).ready(function(){
// Load the content for the first time.
loadContent();
});
jQuery的代理只是重置了'this'在函数中指向的东西..所以,你可以替换一个数字中的传递来重置范围:)(如果这有意义......漫长的一天)