Utilizzo di jQuery $ (this) con ES6 Arrow Functions (lessicale this binding)


129

Usare le funzioni freccia ES6 con l' thisassociazione lessicale è fantastico.

Tuttavia, mi sono imbattuto in un problema un momento fa usandolo con un tipico clic di jQuery:

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

Utilizzando invece una funzione freccia:

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

E poi $(this)viene convertito in chiusura di tipo ES5 (self = this).

È un modo per fare in modo che Traceur ignori "$ (this)" per l'associazione lessicale?


questo sembra un perfetto esempio di quando non usare una funzione freccia poiché .on()ha effettivamente un thisvalore utile per te. Per me è molto più chiaro thisriferirsi all'obiettivo dell'evento che dover passare l'evento e trovare l'obiettivo manualmente. Non ho giocato molto con le funzioni freccia, ma sembra che sarebbe fonte di confusione andare avanti e indietro con funzioni anonime.
robisrob

Risposte:


194

Questo non ha nulla a che fare con Traceur e spegnere qualcosa, è semplicemente così che funziona ES6. È la funzionalità specifica che stai chiedendo utilizzando =>invece di function () { }.

Se vuoi scrivere ES6, devi scrivere ES6 tutto il tempo, non puoi entrare e uscire da esso su certe righe di codice e sicuramente non puoi sopprimere o alterare il modo in cui =>funziona. Anche se potessi, finiresti con una versione bizzarra di JavaScript che solo tu capisci e che non funzionerebbe mai correttamente al di fuori del tuo Traceur personalizzato, che sicuramente non è il punto di Traceur.

Il modo per risolvere questo particolare problema non è utilizzare thisper accedere all'elemento cliccato, ma utilizzare invece event.currentTarget:

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

jQuery fornisce event.currentTargetspecificamente perché, anche prima di ES6, non è sempre possibile per jQuery imporre un thissulla funzione di callback (cioè, se era associato a un altro contesto tramite bind.


4
Nota, sebbene diverga solo per le .onchiamate delegate , in thisrealtà lo è event.currentTarget.
loganfsmyth

Questa risposta va bene? Come ha notato loganfsmyth, this== event.currentTarget. No?
Léon Pelletier

3
@ LéonPelletier No. thise event.currentTargetsono gli stessi a meno che non thissiano vincolati all'ambito di inclusione , come con una funzione freccia ES6.
meagar

8
se vuoi salvare del codice, puoi anche destrutturarlo: ({currentTarget}) => {$ (currentTarget) .addClass ('active')}
Frank

55

Associazione di eventi

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

Ciclo continuo

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

Cerchi $jQueryElements.each()? jQuery invia effettivamente alcuni argomenti a ciascun oggetto, quindi non ne hai affatto bisogno => È$(...).each((index, el) => console.log(el))
jave.web

53

Un altro caso

La risposta in alto è corretta e l'ho votata.

Tuttavia, c'è un altro caso:

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

Potrebbe essere risolto come:

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

Questo è un errore storico in jQuery che mette l' indice , invece dell'elemento come primo argomento:

.each (funzione)


Tipo di funzione : Function( Integer index, Element element )
una funzione da eseguire per ogni elemento corrispondente.

Vedi: https://api.jquery.com/each/#each-function


1
Lo stesso per funzioni come$('jquery-selector').map
Nicholas Siegmundt

Questo mi è stato molto utile da usare in cose come $ ('jquery-selector'). Filter ecc ... grazie per averlo reso così chiaro.
R Jones

8

(Questa è una risposta che ho scritto per un'altra versione di questa domanda, prima di apprendere che era un duplicato di questa domanda. Penso che la risposta raccolga le informazioni abbastanza chiaramente, quindi ho deciso di aggiungerla come wiki della comunità, sebbene sia in gran parte solo diversa fraseggio delle altre risposte.)

Non puoi. Questo è metà del punto delle funzioni freccia, si chiudono thisinvece di avere le proprie impostate da come vengono chiamate. Per il caso d'uso nella domanda, se si desidera thisimpostare jQuery quando si chiama il gestore, il gestore dovrebbe essere una functionfunzione.

Ma se hai un motivo per usare una freccia (forse vuoi usarla thisper cosa significa fuori dalla freccia), puoi usare e.currentTargetinvece di thisse ti piace:

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

L' currentTargetoggetto evento è lo stesso di quello thissu cui si imposta jQuery quando si chiama il gestore.


5

Come ha detto Meager nella sua risposta su questa stessa domanda Se vuoi scrivere ES6, devi scrivere ES6 tutto il tempo ,

quindi se stai usando la funzione freccia di ES6:, (event)=>{}allora devi usare al $(event.currentTarget)posto di $(this).

puoi anche usare un modo più bello e pulito di usare currentTarget come ({currentTarget})=>{},

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

originariamente questa idea è stata commentata da rizzi frank nella risposta di @ Meager, e l'ho sentita utile e penso che non tutte le persone leggeranno quel commento, quindi l'ho scritto come un'altra risposta.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.