06.02.2026

JavaScript’te WeakMap & WeakSet: Bellek Sızıntısı Yaşamadan Önbellek ve Metadata Yönetimi

DOM node’larına metadata eklerken ve önbellek kurarken WeakMap/WeakSet ile GC-dostu çözümler.

Web uygulamalarında sık gördüğüm iki ihtiyaç var: (1) bir objeye/DOM elemanına “metadata” iliştirmek, (2) pahalı hesapların sonucunu önbelleğe almak. Bunları Map ile yaptığınızda, anahtar olarak tuttuğunuz objeler çöp toplayıcı (GC) tarafından temizlenmeyebilir ve zamanla bellek sızıntısına dönüşebilir. Burada WeakMap ve WeakSet devreye giriyor.

WeakMap / WeakSet nedir?

  • WeakMap: anahtarları sadece obje olan bir map. Anahtara başka yerden referans kalmazsa GC onu temizleyebilir.
  • WeakSet: sadece obje tutan set. Obje başka yerde kullanılmıyorsa yine GC temizleyebilir.

Önemli kısıtlar:

  • WeakMap/WeakSet iterable değildir (for..of, size yok). Çünkü içerik “her an” GC ile değişebilir.
  • Anahtar primitive olamaz (string, number vs.).

1) DOM elemanına metadata eklemek (dataset yerine)

dataset her zaman uygun olmayabilir: string’e zorlar, DOM’a yazdığı için debug/inspect sırasında kirletir, bazen güvenlik ve ayrıştırma maliyeti doğurur.

const meta = new WeakMap();

function attachMeta(el, data) {
  meta.set(el, data);
}

function getMeta(el) {
  return meta.get(el);
}

const button = document.querySelector("#buy");
attachMeta(button, { variantId: 42, source: "recommendation" });

button.addEventListener("click", () => {
  const info = getMeta(button);
  console.log("clicked with", info);
});

button DOM’dan kaldırılıp başka referans kalmadığında meta tarafında da otomatik “buharlaşır”. Map kullansaydınız, meta içindeki anahtar referansı yüzünden DOM node’u bellekten atılamayabilirdi.

2) GC-dostu memoization (pahalı hesap önbelleği)

Bir objeye bağlı hesapların sonucunu saklamak için WeakMap iyi bir tercihtir.

const cache = new WeakMap();

function expensiveScore(user) {
  if (cache.has(user)) return cache.get(user);

  // Örnek pahalı hesap
  const score = user.actions.reduce((acc, a) => acc + a.weight, 0);

  cache.set(user, score);
  return score;
}

let u = { actions: [{ weight: 2 }, { weight: 5 }] };
console.log(expensiveScore(u));
console.log(expensiveScore(u)); // cache hit

u = null; // başka referans yoksa cache de GC ile temizlenebilir

Bu yaklaşım, uzun ömürlü uygulamalarda (SPA, dashboard, admin panel) “gördüğün kullanıcıları/nesneleri cache’leyeyim” deyip büyüyen Map sorununu azaltır.

3) “Bu objeyi daha önce işledim mi?”: WeakSet ile idempotent işler

Bazı işlemler aynı nesneye iki kere uygulanmamalı (ör. DOM üzerinde dekorasyon, tek seferlik init).

const initialized = new WeakSet();

function enhanceCard(cardEl) {
  if (initialized.has(cardEl)) return;
  initialized.add(cardEl);

  // Tek seferlik iyileştirme
  cardEl.classList.add("enhanced");
}

Kart DOM’dan kalkınca initialized içinde kalıp şişmez.

Ne zaman WeakMap/WeakSet kullanmalı?

  • Anahtarın bir obje olduğu ve ömrünü sizin değil, GC’nin yönetmesini istediğiniz durumlarda
  • DOM elemanlarına “yan bilgi” bağlarken
  • Objeye bağlı memoization/önbellek yaparken
  • Tek seferlik işaretleme (processed/initialized) yaparken

Ne zaman kullanmamalı?

  • Listelemek, saymak, raporlamak istiyorsanız (size/iteration yok)
  • Anahtarınız primitive ise (o zaman Map/Set)
  • Verinin yaşam döngüsünü bilinçli yönetmeniz gerekiyorsa (ör. manuel invalidation, TTL)

WeakMap/WeakSet’in güzelliği şu: doğru yerde kullanıldığında bellek yönetimini “daha az dert” hâline getirir; yanlış yerde kullanıldığında ise debug etmeyi zorlaştırabilir. Metadata ve cache gibi yardımcı bilgiler için ideal bir araç.