Closure tuzakları
Döngü içinde closure oluştururken yapılan sık hatayı ve nasıl düzeleceğini öğrenirsin.
Closure tuzağı
Klasik bir closure tuzağı: döngüde var ile closure üretmek. var fonksiyon kapsamlı olduğundan, tüm closure'lar aynı i değişkenini yakalar. Döngü bitince i son değerinde kalır; closure'lar çağrıldığında hepsi aynı son değeri döndürür.
Buna stale reference denir: closure eski bir değere işaret ettiğini sanar ama aslında hep son değeri görür.
let ile çözüm
Çözüm: var yerine let kullan. let blok kapsamlıdır; her yineleme yeni bir bağ (binding) oluşturur. Her closure kendi i'sini yakalar, böylece çağrıldığında doğru indeksi döndürür.
Bu yüzden modern JavaScript'te döngülerde hep let tercih edilir. Eski kodlarda var görsen de yeni kod yazarken let kullan; bu basit değişiklik sinsi hatalardan korur.
Uygulama Döngüde closure düzelt
makeFunctions() adında bir fonksiyon tanımla. İçinde boş bir fns dizisi oluştur. for (let i = 0; i < 3; i++) döngüsüyle her yinelemede fns.push(function() { return i; }) yapsın. Sonunda fns'i döndürsün. Çağırıp üç elemanını da konsola yazdır.
Örnek çözümü göster
function makeFunctions() {
const fns = [];
for (let i = 0; i < 3; i++) {
fns.push(function() {
return i;
});
}
return fns;
}
const fns = makeFunctions();
console.log(fns[0]());
console.log(fns[1]());
console.log(fns[2]());
Kendini test et
-
Tuzak terimlerini eşleştir
- loop capture
- Döngüde closure'ın değişkeni yakalaması
- stale reference
- Eski değere işaret eden referans
- let in loop
- Her yineleme için yeni kapsam
-
Döngüde var ile closure oluşturunca ne olur?
- Her closure kendi indeksini yakalar
- Tüm closure'lar döngünün son indeksini yakalar
- Döngü hiç çalışmaz
- Closure'lar otomatik sıfırlanır
Cevabı göster
Tüm closure'lar döngünün son indeksini yakalar — Doğru. var fonksiyon kapsamlıdır; tüm closure'lar aynı i'yi paylaşır ve döngü bitince son değerde kalır.
-
Doğru döngüyü seç
// Hatalı: tüm fonksiyonlar aynı i'yi yakalar const wrong = []; for (var i = 0; i < 3; i++) { wrong.push(() => i); } // Doğru: her yineleme yeni i bağlar const right = []; for (____) { right.push(() => i); }Cevabı göster
// Hatalı: tüm fonksiyonlar aynı i'yi yakalar const wrong = []; for (var i = 0; i < 3; i++) { wrong.push(() => i); } // Doğru: her yineleme yeni i bağlar const right = []; for (let i = 0; i < 3; i++) { right.push(() => i); }