292

にコンテキストを渡すにはどうすればよいsetTimeoutですか? 1000ミリ秒後this.tip.destroy()に呼び出したい。this.options.destroyOnHideどうやってやるの?

if (this.options.destroyOnHide) {
     setTimeout(function() { this.tip.destroy() }, 1000);
} 

上記を試してみるとthis、ウィンドウを参照します。

4

6 に答える 6

443

編集:要約すると、2010 年にこの質問がされたとき、この問題を解決する最も一般的な方法は、setTimeout関数呼び出しが行われたコンテキストへの参照を保存することでした。これは、グローバル オブジェクトを指してsetTimeout関数を実行するためです。this

var that = this;
if (this.options.destroyOnHide) {
     setTimeout(function(){ that.tip.destroy() }, 1000);
} 

その1年前にリリースされたばかりのES5仕様では、bindmethodが導入されました。これは、まだ広くサポートされておらず、使用するにはポリフィルが必要だったため、元の回答では提案されていませんでしたが、今ではどこにでもあります:

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);
}

以下も参照してください。

于 2010-01-25T05:40:08.167 に答える
234

関数ラッパー @CMS への既成のショートカット (シンタックス シュガー) が用意されています。(以下では、必要なコンテキストが であると仮定しますthis.tip。)


ECMAScript 2015 (すべての一般的なブラウザーとスマートフォン、Node.js 5.0.0+)

事実上すべての JavaScript 開発 (2020 年)で、ECMAScript 2015 (Harmony/ES6/ES2015) 仕様の一部である太い矢印関数を使用できます。

アロー関数式(太いアロー関数とも呼ばれます) は、関数式に比べて構文が短く、this値 [...] を字句的にバインドします。

(param1, param2, ...rest) => { statements }

あなたの場合、これを試してください:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}

ECMAScript 5 (古いブラウザーとスマートフォン、Node.js) および Prototype.js

ECMA-262、第 5 版 (ECMAScript 5)またはNode.jsと互換性のあるブラウザーを対象とする場合、(2020 年には) すべての一般的なブラウザーと古いブラウザーを意味し、 を使用できます。オプションで、任意の関数引数を渡して部分関数を作成できます。Function.prototype.bind

fun.bind(thisArg[, arg1[, arg2[, ...]]])

繰り返しますが、あなたの場合、これを試してください:

if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}

同じ機能がPrototype にも実装されています (他のライブラリはありますか?)。

Function.prototype.bindカスタムの下位互換性が必要な場合は、このように実装できます(ただし、注意事項を守ってください)。


jQuery

thisすでに jQuery 1.4 以降を使用している場合は、関数のコンテキストを明示的に設定するための既製の関数があります。

jQuery.proxy() : 関数を受け取り、常に特定のコンテキストを持つ新しい関数を返します。

$.proxy(function, context[, additionalArguments])

あなたの場合、これを試してください:

if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}

Underscore.jslodash

Underscore.js と lodash で_.bind(...)12として利用できます。

bind関数をオブジェクトにバインドします。つまり、関数が呼び出されるたびに、の値がthisオブジェクトになります。必要に応じて、引数を関数にバインドして事前入力します (部分適用とも呼ばれます)。

_.bind(function, object, [*arguments])

あなたの場合、これを試してください:

if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}

于 2012-01-10T08:01:31.110 に答える
31

Internet Explorer 以外のブラウザーでは、遅延後に一緒にパラメーターを関数に渡すことができます。

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

したがって、これを行うことができます:

var timeoutID = window.setTimeout(function (self) {
  console.log(self); 
}, 500, this);

これは、スコープ ルックアップ ( thistimeout / interval 式の外側の変数へのキャッシュ) よりもパフォーマンスの点で優れており、クロージャを作成します ( $.proxyorを使用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);
    }
});
@*/
于 2012-02-15T17:35:59.973 に答える
5

注: これは 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);
于 2014-05-26T12:19:38.803 に答える
2

を使用している場合はunderscore、使用できますbind

例えば

if (this.options.destroyOnHide) {
     setTimeout(_.bind(this.tip.destroy, this), 1000);
}
于 2012-10-20T17:18:16.033 に答える