Pass correct “this” context to setTimeout callback?
如何将上下文传递到
1 2 3 | if (this.options.destroyOnHide) { setTimeout(function() { this.tip.destroy() }, 1000); } |
当我尝试上述方法时,
您需要保存对执行
1 2 3 4 | var that = this; if (this.options.destroyOnHide) { setTimeout(function(){that.tip.destroy()}, 1000); } |
您可以很容易地证明
1 2 3 4 5 6 | (function () { alert(this); // alerts hello setTimeout(function(){ alert(this == window); // true }, 1000); }).call("hello"); |
参见:
- 设置超时-这个问题
有现成的快捷方式(语法糖)到用回答的函数包装器@cms。(假设您需要的上下文是
如果您的目标浏览器与ECMA-262、第5版(ECMAScript 5)或node.js兼容,则可以使用
1 | fun.bind(thisArg[, arg1[, arg2[, ...]]]) |
同样,在您的情况下,请尝试以下操作:
1 2 3 | if (this.options.destroyOnHide) { setTimeout(this.tip.destroy.bind(this.tip), 1000); } |
同样的功能也在原型中实现(其他库?).
如果您希望自定义向后兼容性(但请遵守注释),可以这样实现
对于尖端开发(2015),您可以使用fat arrow函数,这是ecmascript 2015(harmony/es6/es2015)规范(示例)的一部分。
An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the
this value [...].
1 | (param1, param2, ...rest) => { statements } |
在您的情况下,请尝试以下操作:
1 2 3 | if (this.options.destroyOnHide) { setTimeout(() => { this.tip.destroy(); }, 1000); } |
JQuery
如果您已经在使用jquery 1.4+,那么有一个现成的函数可以显式地设置函数的
jQuery.proxy(): Takes a function and returns a new one that will always have a particular context.
1 | $.proxy(function, context[, additionalArguments]) |
在您的情况下,请尝试以下操作:
1 2 3 | if (this.options.destroyOnHide) { setTimeout($.proxy(this.tip.destroy, this.tip), 1000); } |
下划线.js,lodash
它可以在underline.js和lodash中使用,如
bind Bind a function to an object, meaning that whenever the function is called, the value of
this will be the object. Optionally, bind arguments to the function to pre-fill them, also known as partial application.
1 | _.bind(function, object, [*arguments]) |
在您的情况下,请尝试以下操作:
1 2 3 | if (this.options.destroyOnHide) { setTimeout(_.bind(this.tip.destroy, this.tip), 1000); } |
bind jquery underline.js ecmascript-5 prototypejs node.js
在Internet Explorer以外的浏览器中,可以在延迟后一起将参数传递给函数:
1 | var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]); |
所以,你可以这样做:
1 2 3 | var timeoutID = window.setTimeout(function (self) { console.log(self); }, 500, this); |
这在性能方面比范围查找(将
通过WebReflection使其在IES中工作的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /*@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); } }); @*/ |
注意:这在IE中不起作用
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); |
如果您使用的是
例如。
1 2 3 | if (this.options.destroyOnHide) { setTimeout(_.bind(this.tip.destroy, this), 1000); } |