コンテキストをsetTimeout
に渡すにはどうすればよいですか? 1000ミリ秒後にthis.options.destroyOnHide
の場合はthis.tip.destroy()
を呼び出したいです。どうやってやるの?
if (this.options.destroyOnHide) {
setTimeout(function() { this.tip.destroy() }, 1000);
}
上記を試してみると、this
はウィンドウを指します。
EDIT:要約すると、2010年にこの質問が行われたとき、この問題を解決する最も一般的な方法は、setTimeout
のコンテキストへの参照を保存することでしたsetTimeout
はグローバルオブジェクトを指すthis
で関数を実行するため、関数呼び出しが行われます。
var that = this;
if (this.options.destroyOnHide) {
setTimeout(function(){ that.tip.destroy() }, 1000);
}
その1年前にリリースされたES5仕様では、 bind
method が導入されましたが、これはまだ広くサポートされておらず、使用するためにポリフィルが必要だったため、元の回答では提案されませんでしたしかし、今ではどこにでもあります:
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);
}
こちらもご覧ください:
@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);
}
同じ機能が Prototypeで実装 (他のライブラリ?)でもあります。
Function.prototype.bind
は次のように実装できます カスタムの後方互換性が必要な場合(ただし注意事項を確認してください).
最先端の開発(2015)では、太い矢印関数を使用できます。これは ECMAScript 2015(Harmony/ES6/ES2015)仕様の一部 ( 例 )。
arrow function expression (別名fat arrow function)は、関数式と比較して構文が短く、
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);
}
Internet Explorer以外のブラウザーでは、遅延後に関数にパラメーターを一緒に渡すことができます。
var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
だから、あなたはこれを行うことができます:
var timeoutID = window.setTimeout(function (self) {
console.log(self);
}, 500, this);
これは、スコープルックアップ(this
をタイムアウト/間隔式以外の変数にキャッシュする)よりもパフォーマンスの点で優れており、クロージャーを作成する($.proxy
またはFunction.prototype.bind
を使用して)。
IEで 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);
}
});
@*/
注:これは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);
underscore
を使用している場合は、bind
を使用できます。
例えば。
if (this.options.destroyOnHide) {
setTimeout(_.bind(this.tip.destroy, this), 1000);
}