-1

私はこのようなコードを持っています:

var Obj = {
  el : document.getElementById("elementId"),

  doSomething : function(){ this.el.property = "value" }
};

Obj.el.addEventListener('click', Obj.doSomething);

しかし、クリックイベントが発生したときに要素this.el は未定義ですか? これが起こる原因は何ですか?

注: このエディターでコード内の行を分割する方法がわかりません。そのため、1 行になっています。

4

1 に答える 1

5

JavaScriptでは(同様の構文を持つ他のほとんどの言語とは異なり)、関数が定義されている場所ではなく、関数が呼び出される方法thisによって完全に定義されます。関数内でのイベントハンドラーの呼び出し方法は、オブジェクトを参照しません。this

次の3つの方法で修正できます。

  1. ES5対応のブラウザをターゲットにしている場合、またはES5の「シム」を含む場合は、次を使用しますFunction#bind

    var Obj = {
      el : document.getElementById,
    
      doSomething : function(){ this.el.property = "value" }
    };
    
    Obj.el.addEventListener('click', Obj.doSomething.bind(Obj));
    
  2. それ以外の場合は、クロージャーを使用します。

    var Obj = {
      el : document.getElementById,
    
      doSomething : function(){ this.el.property = "value" }
    };
    
    Obj.el.addEventListener('click', function(event) {
        return Obj.doSomething(event);
    });
    
  3. RobGがコメントで指摘したように、オブジェクトは1つ Objしかないため(コンストラクター関数や、必要に応じて複数を作成するものではなく)、次Objではなく変数()を使用してそのオブジェクトを参照できthisます。

    var Obj = {
      el : document.getElementById,
    
      // Obj instead of this ---v
      doSomething : function(){ Obj.el.property = "value" }
    };
    
    Obj.el.addEventListener('click', Obj.doSomething);
    

    これは、オブジェクトが定義されているスコープ内で1回限りの場合にのみ機能します(これはあなたのObj例に当てはまります)。あなたがそれに対して持っている唯一の参照がthis(例えば、あなたが持っていなかったObj)であるならば、あなたはこれをすることができず、前の2つのオプションのうちの1つが欲しいでしょう。

もっと:


ただし、あなたのel財産は疑わしいことに注意してください。あなたはそれを次のように定義しました

el : document.getElementById,

...これは、関数elを指していることを意味します。それはおそらくあなたがやろうとしていたことではありません。おそらく、次のように取得したDOM要素を参照することを意図していまし getElementByIdel getElementById

el : document.getElementById("someIdValue"),

詳細はこちら

于 2012-04-15T22:11:28.260 に答える