2009-02-26 13 views
24

私はsetTimeout関数を使用し、別のメソッドを呼び出すメソッドを持っています。最初のロード方法では、2はうまく動作します。しかし、タイムアウト後、method2が定義されていないというエラーが表示されます。私はここで間違って何をしていますか?setTimeoutとJavaScriptの "this"

例:

test.prototype.method = function() 
{ 
    //method2 returns image based on the id passed 
    this.method2('useSomeElement').src = "http://www.some.url"; 
    timeDelay = window.setTimeout(this.method, 5000); 
}; 

test.prototype.method2 = function(name) { 
    for (var i = 0; i < document.images.length; i++) { 
     if (document.images[i].id.indexOf(name) > 1) { 
      return document.images[i]; 
     } 
    } 
}; 
+0

ようにそれを行うことができますES6に:ちょうど "finction" であります質問のタイプミスか、それともあなたのコードにありますか? –

+0

method2の定義とスコープを追加してください。 –

+0

申し訳ありませんが、タイプは –

答えて

38

setTimeout()は、javascriptでグローバルスコープを使用する問題です。基本的には、method()クラスを呼び出していますが、thisからは呼び出していません。その代わりに、setTimeoutに機能methodを使用するように指示するだけで、特定のスコープはありません。

これを修正するには、正しい変数を参照する別の関数呼び出しで関数呼び出しをラップすることができます。 callMethod()は、メソッドの範囲内であるため、

test.protoype.method = function() 
{ 
    var that = this; 

    //method2 returns image based on the id passed 
    this.method2('useSomeElement').src = "http://www.some.url"; 

    var callMethod = function() 
    { 
     that.method(); 
    } 

    timeDelay = window.setTimeout(callMethod, 5000); 
}; 

thatthisことができます:それはこのようなものが見えます。

IEがsetTimeoutに2つ以上のパラメータをサポートしないため、setTimeoutメソッドにパラメータを渡す必要がある場合、この問題はより複雑になります。その場合は、closuresを読んでください。

また、脇役として、method()は常にmethod()を呼び出しますので、あなたは無限ループのために自分自身を設定しています。あなたは、その所有者からthis.methodをオフにスライスし、setTimeoutに単独の関数を渡すとき

+0

これは、私はそれを試してみようとあなたに知らせる –

+0

ねえ、これはmozillaで動作しているわけではない!どんな手掛かり?画像もループしません。最終画像に達すると停止します。 –

+2

あなたはウィザードです。 – ihatecache

7

あなたはsetTimeOutで使用this自体を経由してスコープです。あなたのt est.prototype.method機能内にvar "foo = this;"を作成し、fooを代わりに使用してください。

0

私は、方法2は

はいを​​定義されていないというエラーを取得し、あなたがでそうthisthisを設定し、関連付けを失いますmethod()は、グローバルオブジェクトwindowと同じです。

驚くべきことの説明についてはthis answerを参照してください。thisはJavaScriptで実際に動作します。

39

より洗練されたオプションは、機能の最後に.bind(this)を追加することです。例:

setTimeout(function() { 
     this.foo(); 
    }.bind(this), 1000); 
// ^^^^^^^^^^^ <- fix context 

だから、OPの質問への答えは次のようになります。

test.prototype.method = function() 
    { 
     //method2 returns image based on the id passed 
     this.method2('useSomeElement').src = "http://www.some.url"; 
     timeDelay = window.setTimeout(this.method.bind(this), 5000); 
     //          ^^^^^^^^^^^ <- fix context 
    }; 
+0

サークルが正方形を取得! –

0

あなたは念のために、この

window.setTimeout(() => { 
    this.foo(); 
}, 1000);