2016-05-03 5 views
4

私はスコープが匿名関数を使ってJavaScriptでどのように処理されるかについて私が知っているすべてを無視するような問題を抱えていますが、それは私が考えていない何か他のものかもしれません。JavaScriptクラスのイベントリスナーで古いコンテキスト変数が表示されるのはなぜですか?

function Element(boxElement) { 
    var self = this; 

    // Set jquery instance variables 
    self.pageElement = null; 
    self.boxElement = boxElement; 

    ... blah blah blah 

    // Implement triggers to empty functions 
    self.onElementClicked = function() {}; 

    // Bind listeners 
    self._bind_listeners(); 
} 

bind_listeners方法は、このような

Element.prototype._bind_listeners = function() { 
    var self = this; 

    self.boxElement.on('click', function (e) { 
     // Don't handle if handled already 
     if (e.isDefaultPrevented()) return; 
     console.log("Got past the return"); 
     self.onElementClicked(); 
    }); 
}; 

として定義され、コールバックを設定する方法もあります:

は、私は次のようにコンストラクタで、要素と呼ばれるJavaScriptオブジェクトを、持っていますメソッドonElementClicked:

Element.prototype.on_element_click = function(callback) { 
    var self = this; 
    self.onElementClicked = callback; 
}; 

問題は私が遭遇しているon_element_clickメソッドを使用してコールバックを設定した場合、自分のメソッドは現在のインスタンスを認識しません。インスタンスは構築直後にどのように見えるかを確認します。

もっと具体的には、JQuery要素を参照するboxElementというインスタンス変数があります。また、Chromeのコンソールでは、インスタンス(self)がページの正しい要素を参照していますが、onElementClickedインスタンス変数(およびその他)はリスナー内から設定されていないようです。

私の説明を改訂したり、説明を求めても構いません。実装の観点から

私はこれを行う場合:

// Set default listener for element click 
formElement.on_element_click(function() { 
    console.log("Hello"); 
}); 

リスナーをonElementClickedが設定されて表示されないためこんにちは言うことはありません。

しかし、私が代わりにこれを行う場合:

formElement.boxElement.click(function() { 
    console.log("Hello"); 
}); 

それは成功したと言い、「こんにちは」と私は混乱します。

+0

問題を引き起こしている最初の例の 'formElement'の代わりに' .boxElement'プロパティにイベントをバインドするのに失敗していませんか? – Josh

+0

最初の例は私がしたいことです。 boxElement変数は、プライベートである/そうでなければならない/存在しないインスタンス変数です。 on_element_clickメソッドは、コールバックを格納し、boxElement.clickの独自のリスナーを使用してコールバックを実行することになっています。 後でこのコールバックメソッドを新しいものでオーバーライドする可能性があるため、私はそれを第2の方法(単なる良いオブジェクト指向設計とは別に)で行うことができません。 (古いコールバックメソッドを意図的に削除する) –

+0

プレーンな要素とイベントリスナ(jQueryではなく)で動作するようです。https://jsfiddle.net/fpfofczy/ - あなたのやり方に似ているかどうかは分かりません。 – skyline3000

答えて

0

このようなエラーがどのように発生する可能性があるかという良い例です。 (offtopic:このエラーを発生させるための他の方法については自由に回答してください - それは非常に非直感的な問題であり、常に外部要因によるものです)

私がテストしたクラスはaクラス私の要素クラス - しかし、それは非常に間違って非常に/非常に非常に悪い!

は同様に、それはこれを投稿することであるとして恥ずかしい、ここで私の「サブクラス」(すぐに見かけ上の理由のために引用符)の元コンストラクタがあります:

function StrikeoutFormElement (formElement) { 
    var self = this; 

    // Set reference to form element 
    self.fe = formElement; 

    $.extend(self, self.fe); 

    // Override methods 
    self.on_reposition(function() { 
     self._on_reposition(); 
    }); 
} 

私が何かを上書きするjQueryのオブジェクト拡張機能とハックの回避策を使用しました。私はOOPのためにJQueryの拡張を決して使用しないという難しい方法を学んだ。それは、言語ツールとしてではなく、データ操作用であるためだ。

新しいコンストラクタは次のようになります。

function StrikeoutFormElement (elem) { 
    var self = this; 

} 
// Extend the FormElement prototype 
StrikeoutFormElement.prototype = Object.create(Element.prototype); 
StrikeoutFormElement.prototype.constructor = Element; 

これはどこかMDNの記事に記載されている方法です。誰かが私にそれを打つことがない場合、私はそれを見つけると、私はソースを投稿します。

このあいまいな問題を見て、それを理解しようとした人には大声で叫ぶ!

+1

この記事でしたか? [クラスと継承](https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Contributor_s_Guide/Classes_and_Inheritance)、もしあなたの答えに自由に追加してください。そして、あなた自身が酷いことはしないでください。あなたは単に有用なことを学び、あなたの質問に従いました。おそらく同様の問題を持つ他の人を助けるでしょう。 –

関連する問題