2009-04-02 11 views
25

関数barが呼び出されたときの "this"の動作は私を困惑させます。以下のコードを参照してください。 barがhtml要素ではなくクリックハンドラから呼び出されたときに、 "this"が普通の古いjsオブジェクトインスタンスになるように手配する方法はありますか?jQuery/JavaScript "this"ポインタの混乱

// a class with a method 

function foo() { 

    this.bar(); // when called here, "this" is the foo instance 

    var barf = this.bar; 
    barf(); // when called here, "this" is the global object 

    // when called from a click, "this" is the html element 
    $("#thing").after($("<div>click me</div>").click(barf)); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
+0

この「fooインスタンスです」と説明してください。次のjsfiddle(http://jsfiddle.net/yY6fp/1/)は 'this.bar()'の 'this'が' window'(グローバル)オブジェクトを評価することを示しています。 –

答えて

33

はの世界へようこそjavascript! :D

あなたはjavascriptスコープとクロージャの領域にさまよっています。短い答えを

this.bar() 

var barf = this.bar; 
barf(); 

を下に実行される(このFOOを指す)、FOOの範囲の下に実行されます。グローバルスコープ。

this.barは、基本的に意味する:

この(FOO)の範囲に、this.barが指し示す機能を実行します。 this.barをbarfにコピーしてbarfを実行したとき。 Javascriptはbarfが指す関数を実行するように解釈され、というが存在しないため、グローバルスコープで実行されます。

これを修正するには、あなたがこのような何かに

barf(); 

を変更することができます。

barf.apply(this); 

これは、それを実行する前に嘔吐するこのの範囲をバインドするためにJavascriptを伝えます。

jqueryイベントでは、匿名関数を使用するか、プロトタイプでバインド関数を拡張してスコープをサポートする必要があります。

詳細情報については:

+2

私は自分自身の用語について100%確信していませんが、私はこの答え(とリンクされているリソース)が '実行コンテキスト'と 'スコープ'を混同していると思います。 'this'が指し示すオブジェクトは*実行コンテキスト*であり、* scope *とは完全に独立しています(クロージャと関係あります)。スコープは関数の作成時に決定され、関数がどの変数を参照できるかを決定します。実行コンテキストは、関数が呼び出されるたびに決定され、 'this'が何を参照するかを決定します。 'スコープ'を '実行コンテキスト'に置き換えてください。そうすれば正しいと思います - 私はそう思います! –

1

このは、機能が接続されていることを常にインスタンスであるためです。 EventHandlerの場合、イベントをトリガしたクラスです。

あなたはこのような無名関数を使って自己を助けることができる:

function foo() { 
    var obj = this; 
    $("#thing").after($("<div>click me</div>").click(function(){obj.bar();})); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
2

あなたはthisが参照すべきかを設定する機能にFunction.applyを使用することがあります。

$("#thing").after($("<div>click me</div>").click(function() { 
    barf.apply(document); // now this refers to the document 
}); 
+1

あなたのコードに閉じた括弧がないことに加えて、* apply *関数は関数ポインタを返す代わりに* barf *関数を即座に実行します。 – Martin

+0

ありがとう、私は今投稿を修正しました:) – moff

5

QuirksModeで入手可能なJavaScriptでthisキーワードの良い説明があります。

0
this.bar(); // when called here, "this" is the foo instance 

fooがないコンストラクタとして、通常の関数として使用する場合、このコメントが間違っているダグラス・クロックフォード であなたができる限り多くをお読みください。 ここに:

foo();//this stands for window