Używanie jQuery $ (this) z funkcjami strzałek ES6 (leksykalne to powiązanie)

129

Używanie funkcji strzałkowych ES6 z thispowiązaniami leksykalnymi jest świetne.

Jednak przed chwilą napotkałem problem, używając go z typowym powiązaniem kliknięcia jQuery:

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

Zamiast tego użyj funkcji strzałki:

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

A następnie $(this)jest konwertowany na zamknięcie typu ES5 (self = this).

Czy jest sposób, aby Traceur ignorował "$ (this)" dla leksykalnego wiązania?

JRodl3r
źródło
wydaje się, że jest to doskonały przykład, kiedy nie należy używać funkcji strzałkowej, ponieważ .on()rzeczywiście ma ona thisprzydatną wartość. Dla mnie jest to o wiele jaśniejsze w thisodniesieniu do celu zdarzenia niż konieczność przechodzenia go i znajdowania celu ręcznie. Nie bawiłem się zbytnio funkcjami strzałkowymi, ale wydaje się, że poruszanie się w tę iz powrotem z funkcjami anonimowymi byłoby mylące.
robisrob

Odpowiedzi:

194

To nie ma nic wspólnego z Traceur i wyłączaniem czegoś, tak po prostu działa ES6. Jest to konkretna funkcja, o którą prosisz, =>zamiast function () { }.

Jeśli chcesz napisać ES6, musisz pisać ES6 cały czas, nie możesz włączać i wyłączać tego w pewnych wierszach kodu, a na pewno nie możesz tłumić ani zmieniać sposobu =>działania. Nawet gdybyś mógł, skończyłbyś z jakąś dziwaczną wersją JavaScript, którą tylko Ty rozumiesz i która nigdy nie działałaby poprawnie poza Twoim dostosowanym Traceur, co zdecydowanie nie jest celem Traceur.

Aby rozwiązać ten konkretny problem, nie należy używać thisdo uzyskania dostępu do klikniętego elementu, ale zamiast tego użyć event.currentTarget:

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

jQuery zapewnia event.currentTargetszczególnie, ponieważ nawet przed ES6 nie zawsze jest możliwe, aby jQuery narzucił funkcję thiswywołania zwrotnego (tj. jeśli została powiązana z innym kontekstem za pośrednictwem bind.

meagar
źródło
4
Uwaga, chociaż różni się tylko dla .onpołączeń delegowanych , w thisrzeczywistości jest event.currentTarget.
loganfsmyth,
Czy ta odpowiedź jest w porządku? Jak zauważył loganfsmyth, this== event.currentTarget. Nie?
Léon Pelletier,
3
@ LéonPelletier No. thisi event.currentTargetsą takie same, chyba że thissą związane z zakresem obejmującym, jak w przypadku funkcji strzałkowej ES6.
meagar
8
jeśli chcesz zapisać jakiś kod, możesz również go zniszczyć: ({currentTarget}) => {$ (currentTarget) .addClass ('active')}
Frank
55

Wiązanie wydarzenia

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

Pętla

Array.prototype.forEach.call($items, (el, index, obj) => {
    var $this = $(el);
    // ... deal with $this
});
Ryan Huang
źródło
Szukasz $jQueryElements.each()? jQuery w rzeczywistości wysyła pewne argumenty do każdego obiektu, więc w ogóle tego nie potrzebujesz => To$(...).each((index, el) => console.log(el))
jave.web
53

Inna sprawa

Najlepsza odpowiedź jest poprawna i zagłosowałem za nią.

Jest jednak inny przypadek:

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

Można to naprawić jako:

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

Jest to historyczny błąd w jQuery, który umieszcza indeks zamiast elementu jako pierwszy argument:

.each (funkcja)


Typ funkcji : Function( Integer index, Element element )
funkcja do wykonania dla każdego dopasowanego elementu.

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

Tyler Long
źródło
1
To samo dotyczy takich funkcji jak$('jquery-selector').map
Nicholas Siegmundt,
Było to dla mnie bardzo przydatne w takich rzeczach jak $ ('jquery-selector'). Filter itp ... dzięki za wyjaśnienie tego.
R Jones
8

(To jest odpowiedź, którą napisałem na inną wersję tego pytania, zanim dowiedziałem się, że była to duplikat tego pytania. Myślę, że odpowiedź zbiera informacje dość wyraźnie, więc zdecydowałem się dodać ją jako wiki społeczności, chociaż jest ona w dużej mierze po prostu inna sformułowanie innych odpowiedzi.)

Nie możesz. To połowa punktu funkcji strzałkowych, zamykają się thiszamiast mieć własne, które są ustawione przez ich wywołanie. W przypadku użycia w pytaniu, jeśli chcesz thisustawić przez jQuery podczas wywoływania procedury obsługi, procedura obsługi musiałaby być functionfunkcją.

Ale jeśli masz powód do używania strzałki (być może chcesz użyć thisdo tego, co to oznacza poza strzałką), możesz użyć e.currentTargetzamiast, thisjeśli chcesz:

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

Obiekt currentTargetzdarzenia jest taki sam, jak ustawia jQuery thispodczas wywoływania programu obsługi.

TJ Crowder
źródło
5

Jak powiedział Meager w swojej odpowiedzi na to samo pytanie, jeśli chcesz pisać ES6, musisz cały czas pisać ES6 ,

więc jeśli używasz funkcji strzałkowej ES6:, (event)=>{}musisz użyć $(event.currentTarget)zamiast $(this).

możesz też użyć ładniejszego i czystszego sposobu korzystania z currentTarget jako ({currentTarget})=>{},

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

pierwotnie pomysł ten został skomentowany przez rizzi Frank w odpowiedzi @ Meager i uznałem , że jest przydatny i myślę, że nie wszyscy ludzie przeczytają ten komentarz, więc napisałem go jako kolejną odpowiedź.

Haritsinh Gohil
źródło