JavaScript-də Taymerlər və Kontekstin Itirilməsi
Taymerləri hadisə işləyicilərində istifadə edərkən bizi kontekstin itirilməsi problemləri gözləyir. Gəlin bir nümunəyə baxaq.
Tutaq ki, bizim bir inputumuz var:
<input id="elem" value="text">
Tutaq ki, bu inputa klik edəndə anonim funksiya işləyəcək və bu funksiyanın daxilində hər saniyə konsola nəsə çıxaran bir taymer işə düşəcək:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // konsola nəsə çıxarırıq
}, 1000);
});
Hələlik hər şey düzgün işləyir. Amma indi tutaq ki,
biz konsola inputumuzun value dəyərini
çıxartmaq istəyirik - bizi sürpriz gözləyir: konsola
undefined çıxacaq:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // undefined çıxacaq
}, 1000);
});
Bütün məsələ ondadır ki, bizdə funksiya içində
funksiya alınır: klik edəndə işləyən xarici anonim
funksiya var və taymerin işə saldığı daxili
anonim funksiya var. Xarici funksiyada this
inputu göstərir, amma daxili funksiyada - yox.
Kontekstin itirilməsi baş verir.
Niyə undefined çıxır, və əvvəlki dərslərdə olduğu kimi
konsolda səhv baş vermir? Çünki setInterval vasitəsilə
çağırılan funksiyanın daxilində this
window obyektini göstərir.
Bu o deməkdir ki, biz window obyektindən value
xüsusiyyətini oxumağa çalışırıq, belə: window.value,
ona görə də onda belə bir xüsusiyyət yoxdur və biz
undefined alırıq (səhv deyil).
Problemi self tətbiq edərək həll edək:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Tutaq ki, belə bir kod verilib:
<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);
});
Kodun müəllifi istəyirdi ki, düyməyə basılanda,
hər saniyə bu düymənin dəyəri 1 vahid artsın.
Lakin, düyməyə basılanda heç nə baş vermir.
Kod müəllifinin səhvini düzəldin. Kod müəllifinə
onun səhvinin niyə baş verdiyini izah etdiyiniz
mətn yazın.