JavaScript'te Zamanlayıcılar ve Bağlam Kaybı
Olay işleyicilerinde zamanlayıcılar kullanılırken bağlam kaybı sorunlarıyla karşılaşırız. Bir örnekle inceleyelim.
Bir input elemanımız olduğunu varsayalım:
<input id="elem" value="text">
Bu inputa tıklandığında bir anonim fonksiyonun çalıştığını ve bu fonksiyonun içinde, her saniye konsola bir şeyler yazdıran bir zamanlayıcının başlatıldığını varsayalım:
let elem = document.querySelector('#elem');
elem.addEventListener('click', function() {
setInterval(function() {
console.log('!!!'); // konsola bir şeyler yazdırır
}, 1000);
});
Şu ana kadar her şey doğru çalışıyor. Ancak şimdi
konsola inputumuzun value değerini
yazdırmak istediğimizde bir sürprizle karşılaşırız:
konsola undefined yazılacaktır:
elem.addEventListener('click', function() {
setInterval(function() {
console.log(this.value); // undefined yazdırılır
}, 1000);
});
Sorun, fonksiyon içinde fonksiyon olmasından
kaynaklanır: tıklama ile çağrılan dış anonim fonksiyon
ve zamanlayıcı tarafından çalıştırılan iç anonim
fonksiyon vardır. Dış fonksiyonda this
inputu gösterir, ancak iç fonksiyonda göstermez.
Bağlam kaybı söz konusudur.
Neden konsola hata mesajı düşmek yerine
undefined yazdırılıyor, önceki derslerde
olduğu gibi? Çünkü setInterval ile
çağrılan fonksiyonun içindeki this,
window'u işaret eder.
Bu, window nesnesinin value
özelliğini okumaya çalıştığımız anlamına gelir, şöyle:
window.value, ancak onda böyle bir özellik
yoktur ve biz de undefined alırız (hata değil).
Sorunu self tanımlayarak düzeltelim:
elem.addEventListener('click', function() {
let self = this;
setInterval(function() {
console.log(self.value);
}, 1000);
});
Aşağıdaki kod verilsin:
<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 yazarı, butona tıklandığında,
butonun değerinin her saniye 1
artmasını istemiştir. Ancak, butona
tıklandığında hiçbir şey olmuyor.
Kod yazarının hatasını düzeltin.
Kod yazarına, hatasının neden kaynaklandığını
açıklayan bir metin yazın.