1

対処できない問題があります。

コンテキストは次のとおりです。継承チェーンが必要であり、この継承に属するオブジェクトのメソッドはイベント ハンドラーである必要があり、同時にオブジェクト プロパティにアクセスできる必要があります。

「新しい」という言葉を使わずに JavaScript を書き、代わりに継承階層を持つ Object.create() を使用しようとしています。というわけで、まずはこのアプローチ。

したがって、残りのオブジェクト (myProto) の設計図があり、次に Object.create を使用してオブジェクトを作成します (またはに割り当てるトリックthisを実行できるクロージャがないようにします)。ここで、このオブジェクトのメソッドを使用して、たとえば div のクリック イベントを処理すると、明らかに DOM オブジェクトが参照され、オブジェクトのプロパティにアクセスできなくなります。thatselfthis

var myProto = {
    init: function (name, value) {
        this.name = name;
        this.value = value;

        return this;
    },
    someHandler: function (e) {
        // Normally I would use this instead of e.target...

        e.target.innerHTML = this.name + this.value; // This does not refer to the object.
    }
};

var myObject = Object.create(myProto).init('myName', 'myValue');
document.getElementById('myDiv').onclick = myObject.someHandler;

ここでフィドル:http://jsfiddle.net/pgPHM/

そして今、「古典的な」アプローチ:私が新しいコンストラクターフォームを使用していた場合、クロージャーでこれを割り当ててからアクセスするのは簡単ですが、Constructor.prototype の関数には問題があります。

var Constructor = function (name, value) {
    var self = this;

    self.name = name;
    self.value = value;
};

Constructor.prototype.someHandler = function () {/*self does not reach this here*/};

jsfiddle: http://jsfiddle.net/ZcG3J/2/

これらのトリッキーなコンテキスト、クロージャーなどなしで、 JSオブジェクトが実際のオブジェクトthisまたはそれ自体を参照するものを持たない理由が本当にわかりません...self

基本的に質問は次のとおりです。

オブジェクトのメソッドをイベント ハンドラーとして使用しながら、オブジェクトにアクセスするにはどうすればよいですか?

4

3 に答える 3

2

単純。関数が "bare" ではなくメソッドとして呼び出された場合、 はthis常に最後のドットの前の単語を参照します。したがって、代わりに:

document.getElementById('myDiv').onclick = myObject.someHandler;

// You're just passing the function here, not calling it.
// It will be called by the onclick handler so `this` is changed

これを行う:

document.getElementById('myDiv').onclick = function(){
    myObject.someHandler();

    // Here, you're actually calling it. So this is the word
    // before the last dot. Which is myObject
}

より現代的なJavaScriptでは、もちろん使用できますbind

document.getElementById('myDiv').onclick = myObject.someHandler.bind(myObject);
于 2013-10-27T21:29:50.393 に答える
2

を使用する場合を除きnewthisJavascript では関数の呼び出し方に応じて によって設定されます。それを正しい方法で呼び出すと、thisあなたが望むものになります。あなたの質問でどのような問題を解決しようとしているのかthisはわかりませんが、決定方法は次のとおりです。

  1. Calling obj.method()-の内部にthis設定されます。objmethod()
  2. function.call()またはを使用して、自分自身になるfunction.apply()ものを制御しthisます。
  3. func()andなどの通常の関数呼び出しを行いthis、グローバル オブジェクトに設定するか、undefined厳密モードかどうかに応じて設定します。
  4. (最新のブラウザーで) を使用して、関数の実行に this の値を "バインド" するために内部的に.bind()自動的に使用される関数スタブを作成します。.apply()
  5. newを使用してコンストラクターを呼び出すと、コンストラクターthis内で新しく作成されたオブジェクトに設定されます。
  6. コールバック関数を引数として任意の関数呼び出し ( など) に渡す場合addEventListener()、ポインターを何に設定するかを決定するのは呼び出し元の関数の責任でthisあり、独自のオブジェクトにバインドされません。DOM に addEventListener()設定thisされます。イベントの原因となったオブジェクト。

特定のオブジェクトのメソッド呼び出しにするイベント ハンドラーの場合、メソッド呼び出しをオブジェクトに関連付ける方法を作成する必要があります。上記のように使用するか、クロージャーに.bind()保存された値を参照できる無名関数を使用できます。this

var self = this;
document.addEventListener('keyup', function(e) {
    self.handleKeys(e);
})

または、次を使用し.bind()ます。

document.addEventListener('keyup', this.handleKeys.bind(this));

.bind()参考までに、クロージャーを作成して最初の例と同じことを行うだけなので、これら 2 つのメソッドの間に実際の機能上の違いはありませんが、それはあなたのために行われます。

于 2013-10-27T21:24:17.737 に答える
1

jsfiddle の最初の問題は、 self がコンストラクターのローカル変数であり、関数の外では使用できないことです。次のコードについてどう思いますか:

var Constructor = function(name, value) {
    var self = this;
    self.name = name;
    self.value = value;
    self.someHandler = function(e) {
        e.target.innerHTML = self.name + self.value; // self undefined    
    }
    return self;
};

var myObject = Constructor('myName', 'myValue');
document.getElementById('myDiv').onclick = myObject.someHandler;

JsFiddle -> http://jsfiddle.net/ZcG3J/4/

希望通りの構造になっていますか?

于 2013-10-27T21:32:49.780 に答える