2012-04-03 4 views
1

JavaScriptでクラスを定義し始めており、キーワードthisには多くの問題があります。ここでJavaScriptで "this"を使用するための決定的な方法

は私が何をしたいの例です:あなたがコメントで見ることができるようにそれが閉鎖内使用されているので

function MyMap() { 

    this.map = new google.maps.Map(....); 

    google.maps.event.addListener(this.map, 'idle', function() { 
     this.mapIdle(); // PROBLEM: "this" undefined 
    }); 

    this.mapIdle = function() { 
     google.maps.event.addListener(marker, 'click', function() { 
      $("button").click(function() { 
       $.ajax({ 
        success: function() { 
         this.map.clearInfoWindows(); // PROBLEM: "this" undefined 
        } 
       }); 
      }); 
     }); 
    } 
} 

thisは、ここでは動作しません。でもあなたは、コールバック関数の周りdefine a callback functionに持っているところ(本気!!)

var that = this; 
google.maps.event.addListener(this.map, 'idle', function() { 
    that.mapIdle(); 
}); 

または:

私のようなworkaroundsを使用して開始しています。

極端に醜いです。どこでも動作しません。私が与えた例のように、ネストされたラムダ関数がたくさんあるとき、私はどのようにクラス属性を使うのか分かりません。

これを行うにはどのような方法が最適ですか?

+2

:あなたはこのようなあなたの呼び出し元のオブジェクトからイベントやAjax呼び出しとthisポインタからthisポインタの両方へのアクセス権を持っている。この方法で[完全に 'の理解この「キーワード」(http://net.tutsplus.com/tutorials/javascript-ajax/fully-understanding-the-this-keyword/)。 –

+3

また、サイドノートとして、Javascriptで何かをする "決定的な方法"を見つけることはほとんどありません。それはそのような言語ではありません。 – nrabinowitz

答えて

3

最も簡単な方法は、(あなたは非セマンティック変数名を気にしない場合、またはthat)あなたとしてself変数を定義することです

function MyMap() { 
    var self = this; 

    // in nested functions use self for the current instance of MyMap 
} 

は、あなたが(彼らはネストされた関数を使用している場合)あなたはプロトタイプに追加する方法のために再びそれをしなければならないことに注目:言及lready

MyMap.prototype.myMethod = function() { 
    var self = this; 
    // use self in nested functions 
}; 

あなたはまた、.bind() method上に読んでください、注意することそれはIEのために働いていない< = 8.

あなたのコールバックの周りにコールバックを定義することにリンクされている質問は、別の問題を解決することです。つまり、適切なクロージャー構造を設定して、適切なループカウンタ値にアクセスするためのループ。これはthis号とは関係ありません。 (必要に応じてselfの技術と簡単に組み合わせることができます)

+0

私はこのようなことをします。 'プライベート'スコープ/サブオブジェクトとは対照的に 'public'と呼ぶこともあります。 – Umbrella

+0

これは非常にうまくいっています、ありがとうございます。 Javascriptは時には痛みを伴うことがあります... –

1

あなただけのオブジェクトとローカルvariblesに機能を割り当てることができ、それらは、コールバックのため閉鎖に含まれています機能:

function MyMap() { 

    var map = new google.maps.Map(....); 

    var mapIdle = function() { 
    google.maps.event.addListener(marker, 'click', function() { 
     $("button").click(function() { 
     $.ajax({ 
      success: function() { 
      map.clearInfoWindows(); 
      } 
     }); 
     }); 
    }); 
    }; 

    this.map = map; 
    this.mapIdle = mapIdle; // Is this needed? 

    google.maps.event.addListener(this.map, 'idle', function() { 
    mapIdle(); 
    }); 

} 
1

JavaScriptでは、thisはすべての関数呼び出しごとに割り当てられます。

これはJavaScriptで認識しておく必要があります。最初は混乱するかもしれませんが、いくつかの簡単なルールが分かれば、実際はかなり簡単です。

それはmyObj.doSomething()のようなメソッド呼び出しの場合は、thisは自動的doSomething()の内側myObjに設定されます。

明示的に関数呼び出しを行うときに、あなたがthisが関数内に設定されているかを制御するためにdoSomething.apply()またはdoSomething.call()を使用することができますthisの値を制御する場合。これがイベントハンドラのコールバックの機能です。彼らは明示的にthisを設定して、イベントを作成したオブジェクト(非常に有用なもの)を指すようにしました。あなたはMDNの.apply().call()についてもっと読むことができます。

通常の関数を呼び出すだけであれば、thisはグローバルオブジェクトに設定され、ブラウザではwindowオブジェクトになります。

すべてのコールバックがthisに変更されるため、すべてのコールバック関数の値はthisになります。あなたのイベントハンドラはコールバックであり、成功ハンドラはAjax関数のコールバックなので、thisの値は周囲のコードから保持されないことを期待するべきです。プロキシ関数やバインド関数を使用する場合の回避策がありますが、通常はクロージャー内の以前の値thisをキャプチャしてそこからvar self = this;のようなものに簡単にアクセスするのと同じように簡単です。

thisポインタをイベントハンドラの外側からアクセスする場合は、イベントハンドラまたはAjax呼び出しでアクセスするローカル変数に保存するだけですそれはイベントハンドラにあります。それを行うためのクリーンな方法はありません。あなたは、これが役に立つかもしれません、注意点として

var self = this; 
    self.mapIdle = function() { 
     google.maps.event.addListener(marker, 'click', function() { 
      $("button").click(function() { 
       $.ajax({ 
        success: function() { 
         self.map.clearInfoWindows(); // PROBLEM: "this" undefined 
        } 
       }); 
      }); 
     }); 
    } 
} 
関連する問題