Pemerhati dan Kehilangan Konteks dalam JavaScript
Apabila menggunakan pemerhati dalam pengendali peristiwa, kita akan menghadapi masalah kehilangan konteks. Mari kita lihat contohnya.
Katakan kita mempunyai satu input:
<input id="elem" value="text">
Katakan apabila klik pada input ini, fungsi tanpa nama akan dilaksanakan dan di dalam fungsi itu, satu pemerhati akan bermula, setiap saat mencetak sesuatu ke konsol:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // mencetak sesuatu ke konsol
}, 1000);
});
Setakat ini semuanya berfungsi dengan betul. Tetapi sekarang katakan
kita mahu mencetak value
input kita ke konsol - kita akan terkejut: konsol
akan mencetak undefined:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // akan mencetak undefined
}, 1000);
});
Semuanya disebabkan oleh fungsi
dalam fungsi: terdapat fungsi tanpa nama luaran,
yang dipanggil pada klik dan fungsi tanpa nama
dalaman, yang dilancarkan oleh pemerhati.
Dalam fungsi luaran this menunjuk
kepada input, tetapi dalam fungsi dalaman - tidak. Berlaku
kehilangan konteks.
Mengapa undefined dicetak, dan tidak menghasilkan
ralat dalam konsol, seperti dalam pelajaran
sebelumnya? Kerana this dalam fungsi,
yang dipanggil melalui setInterval, menunjuk
kepada window.
Ini bermakna kita cuba membaca sifat
value objek window, seperti ini: window.value,
dan sifat sedemikian tiada di dalamnya, dan kita mendapat
undefined (bukan ralat).
Mari betulkan masalah dengan memperkenalkan self:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Katakan kod ini diberikan:
<input type="button" id="elem" value="1">
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
this.value = Number(elem.value) + 1;
}, 1000);
});
Pengarang kod ingin, apabila butang ditekan,
nilai butang itu setiap saat meningkat
sebanyak 1. Namun, apabila butang ditekan
langsung tiada apa yang berlaku. Betulkan ralat
pengarang kod. Tulis teks di mana anda
berikan penjelasan kepada pengarang kod, mengapa berlakunya
ralatnya.