2011-06-25 7 views
1

私はsimple javascript inheritanceのJohn Resigの優れたjavascriptクラスを使用していますが、私は「this」キーワードに関連していくつかの可変スコープの問題の周りに頭を浮かべています。他のjavascriptオブジェクトを含むjavascriptオブジェクトで 'this'をどのように扱うべきですか?

私の拡張クラスは少し私がtouchStartEventHandler内側からEUNodeインスタンスを参照できるようにする必要があり、この

var EUNode = Class.extend({ 

    // Methods 
    //------------------------------------------------------------------------------- 
    init : function(){ 

     this.div = this.createDiv(); 
     this.canDoStuff = true; 
     this.div.addEventListener(touchstart, this.touchStartHandler, false); 

    }, 



    // Create Div 
    //------------------------------------------------------------------------------- 
    createDiv : function(){ 

     // code to create a DIV element, add some classes and do some 
     // other useful stuff 

    }, 

    touchStartHandler : function(event){ 

     // In here, 'this' refers to the div element, so the 
     // following condition doesn't work 
     if(this.canDoStuff){ 

      // do some stuff 

     } 

    } 

}); 

のように見えるので、私は私はそう下記の

var EUNode = Class.extend({ 

    // Methods 
    //------------------------------------------------------------------------------- 
    init : function(){ 

      this._super(); 
      // Store a reference to 'this' globally 
     self = this; 
     self.div = this.createDiv(); 
     self.canDoStuff = true; 
     self.div.addEventListener(touchstart, self.touchStartHandler, false); 

    }, 

    touchStartHandler : function(event){ 

     if(self.canDoStuff){ 

      // Now I can do stuff, but 'self' is now a global variable 
        // which isn't what I want. If there's more than one instance 
        // of EUNode, 'self' references the newest instance. 

     } 

    } 

}); 

を試してみましたループで立ち往生した。グローバルな "自己"の範囲を制限するためには、 "this"キーワードを使用する必要があると思われますが、 "this"はイベントハンドラ内の何かを意味します。任意のヒント?

答えて

2

を試してみてください。あなたが気づいたように、最後のものがグローバルselfを上書きするため、2つのEUNodeインスタンスがあると、すでに問題が発生します。

また、グローバル変数にはtouchStartHandlerが依存しており、この関数の動作全体がこれ以上はっきりしない場合があります。

ちょうど文脈でtouchStartHandlerを呼び出す:

:を参照してくださいあなたはまた、要素 thisをバインドする(他のブラウザの実装のためのリンクを参照してください) .bind()[docs]を使用することができるのECMAScript 5をサポートしているブラウザで

init : function(){ 
    var self = this; // <- local `self` 

    this.div = this.createDiv(); 
    this.canDoStuff = true; 

    // pass a closure, making `self` available inside the function 
    this.div.addEventListener(touchstart, function(event) { 
     self.touchStartHandler(event); 
    }, false); 
}, 

私はそれが常にあるという事実に重点を置きたいと思い

this.div.addEventListener(touchstart, this.touchStartHandler.bind(this), false); 
+0

+1 'var'キーワードを省略すると間違っています。これにより、OPの範囲の問題に関してすべての違いが生じます。 – Tomalak

+0

シンプルシンプルシンプル。私はコードをもっときれいに保つので、 'bind()'関数を好む。残念ながら、これは特にココアWebViewの実装のためのものです。 – gargantuan

+1

@ガルガンタウン:Mmh。たぶんあなたはまだ 'Function.prototype'を拡張することができます。リンクを見てください。しかし、他の方法はどちらも悪くないし、この問題を解決するための一般的なプラクティスです。 –

1

イベントハンドラを設定するときは、匿名関数の「touchStartHandler()」に呼び出しをラップするだけで、クラスの適切なインスタンスを呼び出すことができます。言い換えれば

var boundHandler = function(event) { yourInstance.touchStartHandler(event); }; 

は次に機能「boundHandlerは、」イベントを処理するために使用することができ、かつ実際のコードは常に正しいオブジェクトを参照thisで設定されます。

新しいブラウザでは、同じことを可能にする ".bind()"という関数もあります。代わりに

self.div.addEventListener(touchstart, self.touchStartHandler, false); 

1

はい、グローバル変数は、(一般的に)悪い

self.div.addEventListener(touchstart, function(event) { self.touchStartHandler(event) }, false); 
0

self.touchStartHandler.bind(self)

関連する問題