web-dev-qa-db-ja.com

ES6 Arrow FunctionsでjQuery $(this)を使用する(字句的なthisバインディング)

字句thisバインディングでES6矢印関数を使用するのは素晴らしいことです。

しかし、私は少し前に典型的なjQueryクリックバインディングでそれを使用して問題に遭遇しました:

class Game {
  foo() {
    self = this;
    this._pads.on('click', function() {
      if (self.go) { $(this).addClass('active'); }
    });
  }
}

代わりに矢印関数を使用します。

class Game {
  foo() {
    this._pads.on('click', () => {
      if (this.go) { $(this).addClass('active'); }
    });
  }
}

そして、$(this)はES5(self = this)型クロージャーに変換されます。

字句バインディングでTraceurに「$(this)」を無視させる方法はありますか?

97
JRodl3r

これは、Traceurとは関係なく、何かをオフにします。これは、ES6の仕組みです。これは、function () { }の代わりに=>を使用することで求めている特定の機能です。

ES6を作成する場合は、常にES6を作成する必要があります。特定のコード行でES6を切り替えることはできず、=>の動作を抑制または変更することはできません。たとえできたとしても、あなただけが理解し、カスタマイズされたTraceurの外では正しく動作しない、奇妙なバージョンのJavaScriptができあがります。これはTraceurのポイントではありません。

この特定の問題を解決する方法は、thisを使用してクリックされた要素にアクセスするのではなく、代わりにevent.currentTargetを使用することです。

Class Game {
  foo(){
    this._pads.on('click', (event) => {
      if(this.go) {
        $(event.currentTarget).addClass('active');
      }
    });
  }
}

jQueryはevent.currentTargetを提供します。これは、ES6より前でも、jQueryがコールバック関数にthisを課すことが常に可能とは限らないためです(つまり、 bind によって別のコンテキストにバインドされた場合)。

157
meagar

イベントバインディング

$button.on('click', (e) => {
    var $this = $(e.currentTarget);
    // ... deal with $this
});

Loop

Array.prototype.forEach.call($items, (el, index, obj) => {
    var $this = $(el);
    // ... deal with $this
});
44
Ryan Huang

別のケース

一番上の答えは正解で、私はそれを支持しました。

ただし、別のケースがあります。

$('jquery-selector').each(() => {
    $(this).click();
})

次のように修正できます。

$('jquery-selector').each((index, element) => {
    $(element).click();
})
30
Tyler Long

(これは、この質問の複製であることがわかる前に、この質問の別のバージョンのために書いた回答です。回答は情報をかなり明確にまとめると思うので、コミュニティwikiとして追加することにしました。それは他の答えの言い回しの大部分が異なるだけです。)

できません。それは矢印関数の要点の半分であり、呼び出し方法によって設定される独自のものを持つ代わりに、thisを閉じます。質問のユースケースでは、ハンドラーを呼び出すときにjQueryでthisを設定する場合、ハンドラーはfunction関数である必要があります。

しかし、矢印を使用する理由がある場合(おそらく矢印の外側を意味するthisを使用したい場合)、必要に応じてthisの代わりにe.currentTargetを使用できます。

class Game {
  foo(){
    this._pads.on('click', e => {                   // Note the `e` argument
      if(this.go) {
        $(e.currentTarget).addClass('active');      // Using it
      }
    });
  }
}

イベントオブジェクトのcurrentTargetは、jQueryがハンドラーを呼び出すときにthisに設定するものと同じです。

6
T.J. Crowder

Meager がこの同じ質問に対する答えで言ったように ES6を書きたい場合は、常にES6を書く必要があります

eS6の矢印関数(event)=>{}を使用している場合、$(event.currentTarget)の代わりに$(this)を使用する必要があります。

currentTargetを({currentTarget})=>{}として使用するより優れたよりクリーンな方法を使用することもできます。

Class Game {
  foo(){
    this._pads.on('click', ({currentTarget}) => {
      if(this.go) {
        $(currentTarget).addClass('active');
      }
    });
  }
}

元々、このアイデアは@Meagerの回答で rizzi frank によってコメントされていましたが、私はそれが便利だと感じました。

0
Haritsinh Gohil