CodeBlanks Logo Icon CodeBlanks

Closure tuzakları

JavaScript kursu · Orta seviye · Ders 17/134

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

  1. 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
  2. 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.

  3. 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);
    }

Orta seviye bölümündeki tüm dersler