Apa yang harus Anda ketahui this
this
(alias "konteks") adalah kata kunci khusus di dalam setiap fungsi dan nilainya hanya tergantung pada bagaimana fungsi itu dipanggil, bukan bagaimana / kapan / di mana ia didefinisikan. Itu tidak dipengaruhi oleh lingkup leksikal seperti variabel lain (kecuali untuk fungsi panah, lihat di bawah). Berikut ini beberapa contohnya:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
Untuk mempelajari lebih lanjut this
, lihat dokumentasi MDN .
Cara merujuk ke yang benar this
Jangan gunakan this
Anda sebenarnya tidak ingin mengakses this
secara khusus, tetapi objek yang dimaksud . Itu sebabnya solusi mudah adalah dengan membuat variabel baru yang juga merujuk ke objek itu. Variabel dapat memiliki nama apa saja, tetapi yang umum adalah self
dan that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Karena self
merupakan variabel normal, ia mematuhi aturan lingkup leksikal dan dapat diakses di dalam callback. Ini juga memiliki keuntungan bahwa Anda dapat mengakses this
nilai dari panggilan balik itu sendiri.
Atur this
panggilan balik secara eksplisit - bagian 1
Mungkin terlihat seperti Anda tidak memiliki kontrol atas nilai this
karena nilainya diatur secara otomatis, tetapi sebenarnya tidak demikian.
Setiap fungsi memiliki metode .bind
[docs] , yang mengembalikan fungsi baru yang this
terikat ke suatu nilai. Fungsi ini memiliki perilaku yang persis sama dengan yang Anda panggil .bind
, hanya itu this
yang Anda tetapkan. Tidak peduli bagaimana atau kapan fungsi itu dipanggil, this
akan selalu merujuk pada nilai yang diteruskan.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
Dalam hal ini, kami mengikat panggilan balik this
ke nilai MyConstructor
's this
.
Catatan: Saat mengikat konteks untuk jQuery, gunakan jQuery.proxy
[docs] sebagai gantinya. Alasan untuk melakukan ini adalah agar Anda tidak perlu menyimpan referensi ke fungsi tersebut saat melepaskan ikatan peristiwa. jQuery menanganinya secara internal.
ECMAScript 6 memperkenalkan fungsi panah , yang dapat dianggap sebagai fungsi lambda. Mereka tidak memiliki this
ikatan sendiri . Sebaliknya, this
dilihat dalam lingkup seperti variabel normal. Itu berarti Anda tidak perlu menelepon .bind
. Itu bukan satu-satunya perilaku khusus yang mereka miliki, silakan lihat dokumentasi MDN untuk informasi lebih lanjut.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
Set this
panggilan balik - bagian 2
Beberapa fungsi / metode yang menerima panggilan balik juga menerima nilai yang menjadi this
acuan panggilan balik itu . Ini pada dasarnya sama dengan mengikatnya sendiri, tetapi fungsi / metode melakukannya untuk Anda. Array#map
[Docs] adalah metode semacam itu. Tanda tangannya adalah:
array.map(callback[, thisArg])
Argumen pertama adalah callback dan argumen kedua adalah nilai yang this
harus dirujuk. Berikut adalah contoh yang dibuat-buat:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Catatan: Apakah Anda dapat memberikan nilai atau tidak this
biasanya disebutkan dalam dokumentasi fungsi / metode tersebut. Misalnya, metode jQuery [docs]$.ajax
menjelaskan opsi yang disebut context
:
Objek ini akan dijadikan konteks semua panggilan balik terkait Ajax.
Masalah umum: Menggunakan metode objek sebagai callback / event handler
Manifestasi umum lain dari masalah ini adalah ketika metode objek digunakan sebagai pemanggil balik / penangan kejadian. Fungsinya adalah warga negara kelas satu dalam JavaScript dan istilah "metode" hanyalah istilah sehari-hari untuk fungsi yang merupakan nilai properti objek. Tetapi fungsi itu tidak memiliki tautan spesifik ke objek "mengandung" nya.
Perhatikan contoh berikut:
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = function() {
console.log(this.data);
};
Fungsi this.method
ditugaskan sebagai pengendali event klik, tetapi jika document.body
diklik, nilai yang dicatat akan undefined
, karena di dalam pengendali event, this
merujuk pada document.body
, bukan instance dari Foo
.
Seperti yang telah disebutkan di awal, apa yang this
merujuk tergantung pada bagaimana fungsi dipanggil , bukan bagaimana itu didefinisikan .
Jika kodenya seperti berikut ini, mungkin lebih jelas bahwa fungsi tersebut tidak memiliki referensi implisit ke objek:
function method() {
console.log(this.data);
}
function Foo() {
this.data = 42,
document.body.onclick = this.method;
}
Foo.prototype.method = method;
Solusinya sama dengan yang disebutkan di atas: Jika tersedia, gunakan .bind
untuk secara eksplisit mengikat this
ke nilai tertentu
document.body.onclick = this.method.bind(this);
atau secara eksplisit memanggil fungsi sebagai "metode" objek, dengan menggunakan fungsi anonim sebagai callback / event handler dan menetapkan objek ( this
) ke variabel lain:
var self = this;
document.body.onclick = function() {
self.method();
};
atau gunakan fungsi panah:
document.body.onclick = () => this.method();