如何传递上下文setTimeout
?我想打电话this.tip.destroy()
,如果this.options.destroyOnHide
在1000毫秒。我怎样才能做到这一点?
if (this.options.destroyOnHide) {
setTimeout(function() { this.tip.destroy() }, 1000);
}
当我尝试上述操作时,this
指的是窗口。
如何传递上下文setTimeout
?我想打电话this.tip.destroy()
,如果this.options.destroyOnHide
在1000毫秒。我怎样才能做到这一点?
if (this.options.destroyOnHide) {
setTimeout(function() { this.tip.destroy() }, 1000);
}
当我尝试上述操作时,this
指的是窗口。
Answers:
编辑:总而言之,早在2010年,当有人问这个问题时,解决此问题的最常用方法是保存对进行setTimeout
函数调用的上下文的引用,因为setTimeout
执行函数时要this
指向全局对象:
var that = this;
if (this.options.destroyOnHide) {
setTimeout(function(){ that.tip.destroy() }, 1000);
}
在一年前发布的ES5规范中,它介绍了该bind
方法,但原始答案中并未建议使用该方法,因为该方法尚未得到广泛支持,您需要使用polyfills来使用它,但是现在无处不在:
if (this.options.destroyOnHide) {
setTimeout(function(){ this.tip.destroy() }.bind(this), 1000);
}
该bind
函数将创建一个具有this
预填充值的新函数。
现在在现代JS中,这正是箭头函数在ES6中解决的问题:
if (this.options.destroyOnHide) {
setTimeout(() => { this.tip.destroy() }, 1000);
}
箭头函数没有自己的this
值,访问它时,您正在访问的this
是封闭词法作用域的值。
HTML5还在2011年对计时器进行了标准化,现在您可以将参数传递给回调函数:
if (this.options.destroyOnHide) {
setTimeout(function(that){ that.tip.destroy() }, 1000, this);
}
也可以看看:
this
给函数,则可以使用更少的代码,更少的CPU周期和更少的内存来解决此问题,例如map(),forEach()等。***请参阅:Misha Reyzlin的答案。
功能包装器@CMS有现成的快捷方式(语法糖)。(下面假设您想要的上下文是this.tip
。)
如果您的目标浏览器与ECMA-262,第5版(ECMAScript 5)或Node.js 兼容,则可以使用Function.prototype.bind
。您可以选择传递任何函数参数来创建部分函数。
fun.bind(thisArg[, arg1[, arg2[, ...]]])
同样,请尝试以下方法:
if (this.options.destroyOnHide) {
setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
Function.prototype.bind
如果您希望自定义向后兼容,则可以像这样实现(但请注意说明)。
对于最先进的开发(2015),您可以使用胖箭头功能,该功能是ECMAScript 2015(Harmony / ES6 / ES2015)规范的一部分(示例)。
一个箭头函数表达式(也称为脂肪箭头功能相比函数表达式)具有较短的语法和词汇结合
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);
}
func.bind(context...)
?我想念什么吗?
var boundFn = fn.bind(this); boundFn(); boundFn();
例如。
在Internet Explorer以外的浏览器中,可以在延迟后将参数一起传递给函数:
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
因此,您可以这样做:
var timeoutID = window.setTimeout(function (self) {
console.log(self);
}, 500, this);
就性能而言,这比范围查找(将其缓存this
到timeout / interval表达式之外的变量中),然后创建闭包(使用$.proxy
或Function.prototype.bind
)更好。
通过Webreflection使它在IE中起作用的代码:
/*@cc_on
(function (modifierFn) {
// you have to invoke it as `window`'s property so, `window.setTimeout`
window.setTimeout = modifierFn(window.setTimeout);
window.setInterval = modifierFn(window.setInterval);
})(function (originalTimerFn) {
return function (callback, timeout){
var args = [].slice.call(arguments, 2);
return originalTimerFn(function () {
callback.apply(this, args)
}, timeout);
}
});
@*/
如果您正在使用underscore
,则可以使用bind
。
例如
if (this.options.destroyOnHide) {
setTimeout(_.bind(this.tip.destroy, this), 1000);
}