如何将上下文传递到setTimeout
?我希望在1000毫秒后调用this.tip.destroy()
if this.options.destroyOnHide
。我怎么能这样做?
if (this.options.destroyOnHide) {
setTimeout(function() { this.tip.destroy() }, 1000);
}
当我尝试上述操作时,this
指向窗口。
答案 0 :(得分:278)
您需要保存对进行setTimeout
函数调用的上下文的引用,因为setTimeout
执行函数时this
指向全局对象:
var that = this;
if (this.options.destroyOnHide) {
setTimeout(function(){that.tip.destroy()}, 1000);
}
您可以通过以下方式轻松证明setTimeout
将this
设置为全局对象。
(function () {
alert(this); // alerts hello
setTimeout(function(){
alert(this == window); // true
}, 1000);
}).call("hello");
另见:
答案 1 :(得分:220)
函数包装器@CMS回答了现成的快捷方式(语法糖)。 (下面假设您想要的上下文是this.tip
。)
如果您定位browser compatible with ECMA-262, 5th edition (ECMAScript 5)或Node.js,则可以使用Function.prototype.bind
。您可以选择传递任何函数参数来创建partial functions。
fun.bind(thisArg[, arg1[, arg2[, ...]]])
同样,在你的情况下,试试这个:
if (this.options.destroyOnHide) {
setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
同样的功能也是implemented in Prototype(任何其他库?)。
Function.prototype.bind
can be implemented like this如果您想要自定义向后兼容性(但请注意注释)。
对于尖端开发(2015),您可以使用胖箭头函数,它们是part of the ECMAScript 2015 (Harmony/ES6/ES2015) specification(examples)。
与函数表达式相比,arrow function expression(也称为胖箭头函数)具有更短的语法,并且词法绑定
this
值[...]。
(param1, param2, ...rest) => { statements }
在你的情况下,试试这个:
if (this.options.destroyOnHide) {
setTimeout(() => { this.tip.destroy(); }, 1000);
}
如果您已经在使用jQuery 1.4+,那么有一个现成的函数可以显式设置函数的this
上下文。
jQuery.proxy():获取一个函数并返回一个始终具有特定上下文的新函数。
$.proxy(function, context[, additionalArguments])
在你的情况下,试试这个:
if (this.options.destroyOnHide) {
setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}
它可以在Underscore.js和lodash中使用,_.bind(...)
1,2
bind将一个函数绑定到一个对象,这意味着无论何时调用该函数,
this
的值都将成为对象。 (可选)将参数绑定到函数以预填充它们,也称为部分应用程序。
_.bind(function, object, [*arguments])
在你的情况下,试试这个:
if (this.options.destroyOnHide) {
setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}
答案 2 :(得分:30)
在Internet Explorer以外的浏览器中,您可以在延迟后一起将参数传递给函数:
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
所以,你可以这样做:
var timeoutID = window.setTimeout(function (self) {
console.log(self);
}, 500, this);
这在性能方面优于范围查找(将this
缓存到超出/间隔表达式之外的变量中),然后创建一个闭包(使用$.proxy
或{{1 }})。
使其在Webreflection的IE中运行的代码:
Function.prototype.bind
答案 3 :(得分:3)
注意:这在IE中不起作用
var ob = {
p: "ob.p"
}
var p = "window.p";
setTimeout(function(){
console.log(this.p); // will print "window.p"
},1000);
setTimeout(function(){
console.log(this.p); // will print "ob.p"
}.bind(ob),1000);
答案 4 :(得分:2)
如果您使用的是underscore
,则可以使用bind
。
E.g。
if (this.options.destroyOnHide) {
setTimeout(_.bind(this.tip.destroy, this), 1000);
}
答案 5 :(得分:0)
如果您使用的是 TypeScript,则可以将函数作为参数传递,如下所示:
setTimeout(this.tip.destroy, 1000);
并且 this
上下文将被分配,就像您将调用封装在 JavaScript 中的箭头函数中一样。