Menggunakan jQuery $ (this) dengan ES6 Arrow Functions (leksikal pengikatan ini)

129

Menggunakan fungsi panah ES6 dengan thispengikatan leksikal sangat bagus.

Namun, saya mengalami masalah beberapa saat yang lalu menggunakannya dengan jQuery click binding yang khas:

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

Menggunakan fungsi panah sebagai gantinya:

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

Dan kemudian $(this)akan dikonversi ke penutupan tipe ES5 (self = this).

Apakah cara agar Traceur mengabaikan "$ (this)" untuk pengikatan leksikal?

JRodl3r
sumber
ini sepertinya contoh sempurna tentang kapan tidak menggunakan fungsi panah karena .on()memang memiliki thisnilai yang berguna bagi Anda. Bagi saya itu jauh lebih jelas dengan thismengacu pada target acara daripada harus melewati acara dan menemukan target secara manual. Saya belum banyak bermain dengan fungsi panah tetapi sepertinya akan membingungkan untuk bolak-balik dengan fungsi anonim.
robisrob

Jawaban:

194

Ini tidak ada hubungannya dengan Traceur dan mematikan sesuatu, ini hanyalah cara kerja ES6. Ini adalah fungsi spesifik yang Anda minta dengan menggunakan, =>bukan function () { }.

Jika Anda ingin menulis ES6, Anda perlu menulis ES6 sepanjang waktu, Anda tidak dapat beralih masuk dan keluarnya pada baris kode tertentu, dan Anda pasti tidak dapat menekan atau mengubah cara =>kerjanya. Bahkan jika Anda bisa, Anda hanya akan mendapatkan beberapa versi JavaScript yang aneh yang hanya Anda pahami dan yang tidak akan pernah berfungsi dengan benar di luar Traceur kustom Anda, yang jelas bukan inti dari Traceur.

Cara untuk mengatasi masalah khusus ini tidak menggunakan thisuntuk mendapatkan akses ke elemen yang diklik, melainkan menggunakan event.currentTarget:

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

jQuery menyediakan event.currentTargetsecara khusus karena, bahkan sebelum ES6, tidak selalu mungkin bagi jQuery untuk memaksakan a thispada fungsi callback (yaitu, jika itu terikat ke konteks lain melalui bind.

meagar
sumber
4
Perhatikan, meskipun hanya menyimpang untuk .onpanggilan yang didelegasikan , thissebenarnya event.currentTarget.
loganfsmyth
Apakah jawaban ini oke? Seperti yang dicatat loganfsmyth, this== event.currentTarget. Tidak?
Léon Pelletier
3
@ LéonPelletier No. thisdan event.currentTargetsama kecuali thisterikat ke lingkup penutup, seperti dengan fungsi panah ES6.
meagar
8
jika Anda ingin menyimpan beberapa kode, Anda juga dapat merusaknya: ({currentTarget}) => {$ (currentTarget) .addClass ('active')}
Frank
55

Pengikatan acara

$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
});
Ryan Huang
sumber
Mencari $jQueryElements.each()? jQuery sebenarnya mengirimkan beberapa argumen ke setiap objek sehingga Anda tidak memerlukan ini sama sekali => Ini$(...).each((index, el) => console.log(el))
jave.
53

Kasus lain

Jawaban teratas benar dan saya telah memilihnya.

Namun, ada kasus lain:

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

Bisa diperbaiki sebagai:

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

Ini adalah kesalahan historis di jQuery yang menempatkan indeks , bukan elemennya sebagai argumen pertama:

.each (function)


Jenis fungsi : Function( Integer index, Element element )
Fungsi yang akan dijalankan untuk setiap elemen yang cocok.

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

Tyler Long
sumber
1
Sama untuk fucntions seperti$('jquery-selector').map
Nicholas Siegmundt
Ini sangat berguna bagi saya untuk digunakan dalam hal-hal seperti $ ('jquery-selector']. Filter dll ... terima kasih telah membuatnya begitu jelas.
R Jones
8

(Ini adalah jawaban yang saya tulis untuk versi lain dari pertanyaan ini, sebelum mempelajarinya adalah duplikat dari pertanyaan ini. Saya pikir jawabannya mengumpulkan informasi dengan cukup jelas sehingga saya memutuskan untuk menambahkannya sebagai wiki komunitas, meskipun sebagian besar hanya berbeda frase dari jawaban lainnya.)

Tidak boleh. Itu setengah dari fungsi panah, mereka menutup alih- thisalih memiliki sendiri yang diatur oleh bagaimana mereka dipanggil. Untuk kasus penggunaan dalam pertanyaan, jika Anda ingin thisdisetel oleh jQuery saat memanggil penangan, penangan haruslahfunction fungsi.

Tapi jika Anda memiliki alasan untuk menggunakan panah (mungkin Anda ingin menggunakan thisuntuk apa artinya luar panah), Anda dapat menggunakan e.currentTargetbukan thisjika Anda suka:

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

The currentTargetpada objek acara adalah sama dengan apa yang jQuery set thisuntuk saat memanggil handler Anda.

TJ Crowder
sumber
5

Seperti yang dikatakan Meager dalam jawabannya pada pertanyaan yang sama ini Jika Anda ingin menulis ES6, Anda perlu menulis ES6 setiap saat ,

jadi jika Anda menggunakan fungsi panah dari ES6: (event)=>{}, maka Anda harus menggunakan $(event.currentTarget)bukannya$(this) .

Anda juga dapat menggunakan cara yang lebih baik dan lebih bersih untuk menggunakan currentTarget sebagai ({currentTarget})=>{},

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

awalnya ide ini dikomentari oleh rizzi frank dalam jawaban @ Meager, dan saya merasa berguna dan menurut saya tidak semua orang akan membaca komentar itu jadi saya telah menuliskannya sebagai jawaban yang lain.

Haritsinh Gohil
sumber