jQuery .each和setTimeout不能很好地协同工作
问题描述:
为什么这会返回undefined为所有ID?jQuery .each和setTimeout不能很好地协同工作
var time = 200;
$('.block').each(function() {
setTimeout(function() {
console.log($(this).attr('id'));
}, time);
time += 200;
});
但是这返回的ID就好了?
var time = 200;
$('.block').each(function() {
console.log($(this).attr('id'));
setTimeout(function() {
}, time);
time += 200;
});
我试图创造一种在时间效应在一个沸腾的,这是推动我疯了
答
的this
的CA内的值llback(全局对象)与外部作用域(它是当前元素)不一样。使用以下方法来参考关闭到正确的值:
$('.block').each(function() {
var that = $(this);
setTimeout(function() {
console.log(that.attr('id'));
}, time);
time += 200;
});
这工作,因为传递给setTimeout
的功能是保持可访问其词法范围声明的变量(包括that
)封闭。
的一般这里课是,this
的函数内的值被动态地确定和功能是如何执行上完全取决于:
- jQuery的执行外功能和显式地设定
this
到当前元素(使用call
/apply
)。 -
浏览器在全局环境中执行内部函数,这就是为什么
this
的值为window
的原因。这个简单的测试表明,最后一点:setTimeout(function() { alert(this === window); // true }, 1000)
在现代浏览器中,上述的解决的办法是使用bind
:
$('.block').each(function() {
setTimeout(function() {
console.log($(this).attr('id'));
}.bind(this), time);
time += 200;
});
答
当setTimeout
运行的this
值发生了变化。为了解决这个问题,你可以在你的.each()
循环缓存this
值,使之在提供给匿名函数您setTimeout
:
var time = 200;
$('.block').each(function() {
var $this = $(this);
setTimeout(function() {
console.log($this.attr('id'));
}, time);
time += 200;
});
这里是一个演示:http://jsfiddle.net/FRzWc/
此外,如果你想提高你的循环性能则颇有几分使用$.each()
,而不是.each()
:
var time = 200;
$.each($('.block'), function() {
var $this = $(this);
setTimeout(function() {
$this.text($this.attr('id'));
console.log($this.attr('id'));
}, time);
time += 200;
});