Coba bayangin label sticker kecil yang kamu tempel di belakang TV: "garansi sampai 2027". Pas TV-nya kamu buang, label otomatis ikut hilang — gak ada record di tempat lain yang nyimpen "TV X sebelumnya punya garansi". Itu sifat weak reference di WeakMap/WeakSet: data nempel ke object aslinya, pas objectnya dihapus, data ikut auto-cleanup. Beda dari Map biasa yang nahan reference selama-lamanya, bikin object gak bisa di-garbage-collect = memory leak.
WeakMap:
const privateData = new WeakMap();
function buatUser(nama) {
const user = { nama };
privateData.set(user, { loginCount: 0 });
return user;
}
function login(user) {
const data = privateData.get(user);
data.loginCount++;
}
Perbedaan dengan Map:
| Map | WeakMap | |
|---|---|---|
| Key | Tipe apapun | Hanya object |
| Iterable | Ya (for...of) |
Tidak |
.size |
Ada | Tidak ada |
| Garbage collection | Mencegah | Tidak mencegah |
WeakSet:
const sudahDiproses = new WeakSet();
function proses(obj) {
if (sudahDiproses.has(obj)) {
return "Sudah diproses!";
}
sudahDiproses.add(obj);
return "Memproses...";
}
Use case WeakMap:
- Menyimpan data privat untuk object
- Caching hasil komputasi per object
- Menyimpan metadata DOM element
Use case WeakSet:
- Menandai object yang sudah diproses
- Mencegah circular reference saat traversal
Kapan pakai? Gunakan WeakMap/WeakSet ketika kamu perlu mengasosiasikan data dengan object tanpa mencegah object tersebut di-garbage collect.
🎭 Analogi sehari-hari
WeakMap = label sticker yang nempel di barang. Kalau barang dibuang, label ikut hilang otomatis — tidak ada yang nyimpan record di tempat lain.
Map biasa = rak gudang penyimpanan. Barang nyangkut di rak, tidak akan hilang sampai kamu hapus manual. Bahkan kalau pemilik aslinya sudah lupa keberadaan barang itu, rak tetap menahan = memori boros.
WeakMap cocok untuk metadata yang lifecycle-nya ngikut object.
⚠️ Jebakan yang sering ditemui
- Key HARUS object — primitive (string, number) = TypeError.
weakMap.set("a", 1)error. - Tidak bisa iterate.
for...of,forEach,keys(),values()semua tidak ada. Karena GC bisa hapus key kapan saja, iterate akan tidak konsisten. - Tidak ada
.size. Sama alasan — size tidak deterministik. - Debugging susah — devtools tidak bisa kasih lihat isi WeakMap (kecuali via reference object yang masih hidup).
- Bukan untuk caching dengan primitive key. Pakai Map biasa + LRU eviction kalau perlu bound.
- Asumsi GC terjadi cepat = SALAH. GC asynchronous, tidak deterministik. Jangan andalkan timing untuk logic.
- WeakRef + FinalizationRegistry lebih low-level — untuk monitoring lifecycle, bukan untuk substitute WeakMap.
TL;DR: WeakMap/WeakSet = key/value yang weak reference — pas object key dihapus, entry auto-cleanup (no memory leak). Beda dari Map biasa yang nahan reference selama-lamanya. Key HARUS object (primitive = TypeError). Tidak iterable, tidak ada .size. Use case: data privat per object, metadata DOM, caching per object, mark "sudah diproses". Jangan andalkan timing GC — async, gak deterministik.