web-dev-qa-db-fra.com

Utilisation de jQuery $ (this) avec les fonctions de flèche ES6 (lexical this binding)

L'utilisation des fonctions fléchées ES6 avec la liaison lexicale this est excellente.

Cependant, j'ai rencontré un problème il y a un moment, je l'utilisais avec une liaison de clic jQuery typique:

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

En utilisant une fonction de flèche à la place:

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

Et puis $(this) est converti en fermeture de type ES5 (self = this).

Est-ce qu’une façon de faire en sorte que Traceur ignore "$ (this)" pour la liaison lexicale?

97
JRodl3r

Cela n'a rien à voir avec Traceur et désactiver quelque chose, c'est simplement ainsi que fonctionne ES6. C'est la fonctionnalité spécifique que vous demandez en utilisant => Au lieu de function () { }.

Si vous voulez écrire ES6, vous devez écrire tout le temps, vous ne pouvez pas activer ou désactiver cette fonction sur certaines lignes de code, et vous ne pouvez absolument pas supprimer ou modifier le fonctionnement de =>. Même si vous le pouviez, vous vous retrouveriez avec une version bizarre de JavaScript que vous seul comprenez et qui ne fonctionnerait jamais correctement en dehors de votre Traceur personnalisé, ce qui n'est certainement pas le but de Traceur.

La façon de résoudre ce problème particulier n’est pas d’utiliser this pour accéder à l’élément cliqué, mais d’utiliser event.currentTarget:

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

jQuery fournit event.currentTarget spécifiquement parce que, même avant ES6, il n’est pas toujours possible pour jQuery d’imposer un this à la fonction de rappel (c’est-à-dire si elle était liée à un autre contexte via bind .

157
meagar

Liaison d'événement

$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

Un autre cas

La réponse du haut est correcte et je l’ai votée à la hausse.

Cependant, il y a un autre cas:

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

Peut être corrigé comme:

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

(C’est une réponse que j’ai écrite pour une autre version de cette question, avant d’apprendre que c’était une copie de cette question. Je pense que la réponse rassemble assez clairement les informations, aussi j’ai décidé de l’ajouter comme wiki de communauté, bien que c'est en grande partie une formulation différente des autres réponses.)

Tu ne peux pas. C'est la moitié du point des fonctions de flèche, elles se ferment au-dessus de this au lieu d'avoir leur propre fonction définie par la façon dont elles sont appelées. Pour le cas d'utilisation de la question, si vous souhaitez que this soit défini par jQuery lors de l'appel du gestionnaire, le gestionnaire doit être une fonction function.

Mais si vous avez une raison d'utiliser une flèche (peut-être que vous voulez utiliser this pour ce que cela signifie en dehors de la flèche), vous pouvez utiliser e.currentTarget au lieu de this si vous aimez:

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

Le currentTarget sur l'objet d'événement est identique à ce que jQuery définit this lorsque vous appelez votre gestionnaire.

6
T.J. Crowder

Comme maigre dans sa réponse à la même question si vous voulez écrire ES6, vous devez écrire ES6 tout le temps ,

donc si vous utilisez la fonction de flèche de ES6: (event)=>{}, vous devez alors utiliser $(event.currentTarget) au lieu de $(this).

vous pouvez également utiliser un moyen plus simple et plus propre d’utiliser currentTarget comme ({currentTarget})=>{},

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

à l'origine, cette idée a été commentée par rizzi frank dans la réponse de @ Meager, et je la sentais utile et je pense que tout le monde ne lira pas ce commentaire, je l'ai donc écrit comme une autre réponse.

0
Haritsinh Gohil