Передать правильный" этот " контекст для обратного вызова setTimeout? [дубликат]
этот вопрос уже есть ответ здесь:
как передать контекст в setTimeout
? Я хочу позвонить this.tip.destroy()
Если this.options.destroyOnHide
после 1000 мс. Как я могу это сделать?
if (this.options.destroyOnHide) {
setTimeout(function() { this.tip.destroy() }, 1000);
}
когда я попробую выше,this
относится к окну.
5 ответов
вам нужно сохранить ссылку на контекст, где setTimeout
вызов функции выполнен, потому что setTimeout
выполняет функции this
указывая на глобальный объект:
var that = this;
if (this.options.destroyOnHide) {
setTimeout(function(){that.tip.destroy()}, 1000);
}
вы можете легко доказать, что setTimeout
set this
к глобальному объекту по:
(function () {
alert(this); // alerts hello
setTimeout(function(){
alert(this == window); // true
}, 1000);
}).call("hello");
Читайте также:
есть готовые ярлыки (синтаксический сахар)к функции wrapper @CMS ответил С. (Ниже предполагается, что контекст, который вы хотите, является this.tip
.)
ECMAScript 5 (современных браузеров узел.js) и прототип.js
если вы нацелены браузер совместим с ECMA-262, 5th edition (ECMAScript 5) или узел.js, вы могли бы использовать Function.prototype.bind
. Вы можете выборочно пройти любое аргументы функции для создания частичные функции.
fun.bind(thisArg[, arg1[, arg2[, ...]]])
еще раз, в вашем случае, попробуйте следующее:
if (this.options.destroyOnHide) {
setTimeout(this.tip.destroy.bind(this.tip), 1000);
}
та же функциональность также была реализовано в прототипе (любой другой библиотеки?).
Function.prototype.bind
может быть реализован следующим образом если вы хотите пользовательскую обратную совместимость (но, пожалуйста, соблюдайте Примечания).
ECMAScript 2015 (некоторые браузеры узел.js 5.0.0+)
для передовых разработок (2015) Вы можете использовать функции жирной стрелкой, которые часть спецификации ECMAScript 2015 (Harmony/ES6/ES2015) (примеры).
An выражение функции стрелой (также известный как функция жирной стрелки) имеет более короткий синтаксис по сравнению с функциональными выражениями и лексически связывает
this
значение.[ ..].
(param1, param2, ...rest) => { statements }
в вашем случае, попробуйте это:
if (this.options.destroyOnHide) {
setTimeout(() => { this.tip.destroy(); }, 1000);
}
jQuery
если вы уже используете jQuery 1.4+, есть готовая функция для явной установки this
контекст функции.
С помощью jQuery.proxy (): принимает функцию и возвращает новую, которая всегда будет иметь определенный контекст.
$.proxy(function, context[, additionalArguments])
в вашем случае, попробуйте это:
if (this.options.destroyOnHide) {
setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}
подчеркивания.js, лодашь
он доступен в подчеркивании.js, а также lodash, as _.bind(...)
1,2
bind привязать функцию к объекту, это означает, что всякий раз, когда функция вызывается, значение
this
будет объект. Необязательно связывать аргументы с функцией, чтобы предварительно заполнить их, также известен как частичное применение.
_.bind(function, object, [*arguments])
в вашем случае, попробуйте это:
if (this.options.destroyOnHide) {
setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}
bind в jQuery подчеркивания.js ecmascript-5 prototypejs узел.js
в браузерах, отличных от 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
).
код, чтобы заставить его работать в IEs от Webreflection:
/*@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);
}
Примечание: это не будет работать в 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);