这纯粹是作为研究和个人发展让我感兴趣的。我有一组命名空间的函数/变量。
在 1 个函数中,我需要通过 setTimeout 调用另一个函数,但将范围保持为“this”。我有点挣扎,似乎无法在 setTimeout 运行时绑定(bind)它。
var foo = {
ads: ["foo","bar"],
timeDelay: 3,
loadAds: function() {
var al = this.ads.length;
if (!al)
return; // no ads
for(var i = 0; i < al; i++) {
setTimeout(function() {
this.scrollAd(this.ads[i]);
}.apply(this), this.timeDelay * 1000);
}
},
scrollAd: function(adBlock) {
console.log(adBlock);
}
};
};
.apply(this) 确实改变了范围,因为 console.log 输出正确的对象,但它立即运行该函数,然后异常/警告出现,因为回调仍然为空:
useless setTimeout call (missing quotes around argument?)
有没有一种优雅的方式来做到这一点?我知道我能做到
var _this = this;
并在匿名回调中引用 _this
。例如,在 mootools 中,我会使用 .bind(this)
代替......
不,因为这涉及到动画,我不想在字符串周围使用 ""
因为它需要被评估并且会影响性能......
最佳答案
for(var i = 0; i < al; i++) {
setTimeout(function() {
this.scrollAd(this.ads[i]);
}.apply(this), this.timeDelay * 1000);
}
apply
不绑定(bind)一个函数,它调用它。所以你直接执行滚动,然后将它的返回值(undefined
)传给setTimeout
,这是无效的。
您可能打算在 this
和循环变量(它必须被关闭,否则每次超时都将是相同的循环后值)上使用这样的闭包:
for(var i = 0; i < al; i++) {
setTimeout(function(that, j) {
return function() {
that.scrollAd(that.ads[j]);
};
}(this, i), this.timeDelay * 1000);
}
但是您可能更喜欢使用新的 ECMAScript 第五版函数绑定(bind)功能,它具有更紧凑的语法:
for (var i= 0; i<al; i++)
setTimeout(this.scrollAd.bind(this, this.ads[i]), this.timeDelay*1000);
(在 this answer 的底部有一个 function.bind
的实现,适用于 native 没有它的浏览器。)
关于javascript - 更改 setTimeout 上的匿名函数的范围会导致奇怪的警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1728563/