質問

コールバック関数でオブジェクトを参照する際に、プレーンフレームワークではない古いJavaScriptで問題が発生しています。

function foo(id) {
    this.dom = document.getElementById(id);
    this.bar = 5;
    var self = this;
    this.dom.addEventListener("click", self.onclick, false);
}

foo.prototype = {
    onclick : function() {
        this.bar = 7;
    }
};

新しいオブジェクトを作成するとき(DOMが読み込まれた後、span#testで)

var x = new foo('test');

onclick関数内の「this」は、fooオブジェクトではなくspan#testを指します。

onclick関数内でfooオブジェクトへの参照を取得するにはどうすればよいですか

役に立ちましたか?

解決

(他の回答のコメントに隠されていた説明を抽出)

問題は次の行にあります:

this.dom.addEventListener("click", self.onclick, false);

ここでは、コールバックとして使用される関数オブジェクトを渡します。イベントがトリガーされると、関数が呼び出されますが、オブジェクト(this)との関連付けはありません。

この問題は、次のようにクロージャで関数を(オブジェクト参照で)ラップすることで解決できます。

this.dom.addEventListener(
  "click",
  function(event) {self.onclick(event)},
  false);

変数selfにはクロージャーが作成されたときに this が割り当てられているため、クロージャー関数は後で呼び出されたときにself変数の値を記憶します。

これを解決する別の方法は、ユーティリティ関数を作成することです(そして、 this のバインドに変数を使用しないでください):

function bind(scope, fn) {
    return function () {
        fn.apply(scope, arguments);
    };
}

更新されたコードは次のようになります。

this.dom.addEventListener("click", bind(this, this.onclick), false);

Function.prototype.bind はECMAScript 5の一部であり、同じ機能を提供します。できること:

this.dom.addEventListener("click", this.onclick.bind(this), false);

ES5をまだサポートしていないブラウザーの場合、 MDNは次のシムを提供します

if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  

    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  

    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  

    return fBound;  
  };  
} 

他のヒント

this.dom.addEventListener("click", function(event) {
    self.onclick(event)
}, false);

この問題の解決策を探している jQuery ユーザーの場合、 jQuery.proxy

説明は、 self.onclick がJavaScriptであなたが考えていることを意味しないということです。実際には、オブジェクト self のプロトタイプの onclick 関数を意味します( self 自体を参照することは一切ありません)。

JavaScriptには関数のみがあり、C#のようなデリゲートはありません。そのため、メソッドと、コールバックとして適用されるオブジェクトを渡すことはできません。

コールバックでメソッドを呼び出す唯一の方法は、コールバック関数内でメソッドを呼び出すことです。 JavaScript関数はクロージャーであるため、作成されたスコープで宣言された変数にアクセスできます。

var obj = ...;
function callback(){ return obj.method() };
something.bind(callback);

問題の適切な説明(これまで説明したソリューションの理解に問題がありました)はここで利用可能

このプラグインを作成しました...

有用だと思う

jquery.callback

これはJSの最も紛らわしい点の1つです。「this」変数は最もローカルなオブジェクトを意味しますが、関数もオブジェクトなので、「this」はそこを指します。他にも微妙な点がありますが、私はそれらすべてを覚えていません。

通常、「this」の使用を避け、ローカルの「me」変数を定義して、代わりにそれを使用します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top