JavaScript Notes
Master JavaScript WeakMap: weak object references, garbage collection, private class data, DOM metadata, memoization without memory leaks. Compare WeakMap vs Map with interview Q&A.
A WeakMap is a special Map-like data structure where keys must be objects and the references are weak — meaning they don't prevent the key object from being garbage-collected. When the key object is no longer referenced elsewhere, its WeakMap entry is automatically removed.
💡 Key insight: A regularMapkeeps its key objects alive even if nothing else references them. AWeakMapdoes not — it "lets go" of keys when they become otherwise unreachable. This makes WeakMap perfect for storing metadata associated with objects without causing memory leaks.
WeakMap vs Map
| Feature | Map | WeakMap |
|---|---|---|
| Key types | Any type | Objects only |
| Value types | Any type | Any type |
| Memory behaviour | Keys kept alive (strong ref) | Keys garbage-collected (weak ref) |
| Iterable | ✅ Yes | ❌ No |
size property | ✅ Yes | ❌ No |
clear() method | ✅ Yes | ❌ No |
| Use case | General key-value store | Object metadata / private data |
Creating and Using a WeakMap
const wm = new WeakMap();
let user = { name: "Alice", id: 42 };
let config = { theme: "dark", lang: "en" };
// Keys must be objects (not primitives)
wm.set(user, { loggedIn: true, sessions: 3 });
wm.set(config, { version: 2 });
// get
console.log(wm.get(user)); // { loggedIn: true, sessions: 3 }
console.log(wm.get(config)); // { version: 2 }
// has
console.log(wm.has(user)); // true
console.log(wm.has({})); // false — different object reference
// delete
wm.delete(config);
console.log(wm.has(config)); // false{ loggedIn: true, sessions: 3 }
{ version: 2 }
true
false
falseAutomatic Garbage Collection
const wm = new WeakMap();
let element = document.getElementById("button");
wm.set(element, { clickCount: 0 });
console.log(wm.get(element)); // { clickCount: 0 }
// When the element is removed from DOM and all references dropped:
element = null;
// The WeakMap entry is automatically eligible for garbage collection.
// No need to call wm.delete(element) — it happens automatically.
console.log("Element reference released — GC will clean up WeakMap entry");{ clickCount: 0 }
"Element reference released — GC will clean up WeakMap entry"Use Case 1: Private Data for Class Instances
Before private class fields (#), WeakMap was the idiomatic way to store private state:
const _private = new WeakMap();
class BankAccount {
constructor(owner, balance) {
_private.set(this, { owner, balance, transactions: [] });
}
deposit(amount) {
const data = _private.get(this);
data.balance += amount;
data.transactions.push({ type: "deposit", amount });
console.log(`Deposited $${amount}. Balance: $${data.balance}`);
}
withdraw(amount) {
const data = _private.get(this);
if (amount > data.balance) throw new Error("Insufficient funds");
data.balance -= amount;
data.transactions.push({ type: "withdrawal", amount });
console.log(`Withdrew $${amount}. Balance: $${data.balance}`);
}
getBalance() {
return _private.get(this).balance;
}
}
const account = new BankAccount("Alice", 1000);
account.deposit(500);
account.withdraw(200);
console.log("Balance:", account.getBalance());
// console.log(account.balance); // undefined — truly private via WeakMap"Deposited $500. Balance: $1500" "Withdrew $200. Balance: $1300" "Balance: 1300"
Use Case 2: Memoization Without Memory Leaks
const cache = new WeakMap();
function processUser(user) {
if (cache.has(user)) {
console.log("Cache hit:", user.name);
return cache.get(user);
}
// Expensive computation
const result = { processed: true, name: user.name.toUpperCase(), timestamp: Date.now() };
cache.set(user, result);
console.log("Cache miss — computed:", user.name);
return result;
}
let userA = { name: "alice" };
let userB = { name: "bob" };
processUser(userA);
processUser(userA); // cache hit
processUser(userB);
// When userA goes out of scope, its cache entry is garbage-collected automatically
userA = null;
// No memory leak — regular Map would hold userA alive indefinitely"Cache miss — computed: alice" "Cache hit: alice" "Cache miss — computed: bob"
Use Case 3: Tracking DOM Event Listener State
// "Clicked: Submit" (on button click) // "Listener removed" (on teardown)
Why You Can't Iterate a WeakMap
WeakMap is not iterable by design:
"WeakMap has no iteration API — by design"
Why? If WeakMap were iterable, the JavaScript engine would have to keep all keys alive to iterate them — defeating the weak reference purpose. The non-iterability is a deliberate consequence of weak semantics.
Common Mistakes
- Using a primitive as a key —
wm.set("key", value)throws aTypeError. Keys must be objects. - Expecting
wm.size— WeakMap has nosize. You can't count entries. - Trying to iterate —
forEach,keys(),values(),entries()don't exist on WeakMap. - Using WeakMap when you need to iterate — if you need to list all entries, use a regular
Map. - Using WeakMap for primitive-keyed caches — it can't store
"userId:42"keys. UseMapfor string/number-keyed caches.
Interview Questions
Q1. What makes WeakMap "weak"?
WeakMap holds "weak" references to its keys. If the key object has no other strong references pointing to it, the garbage collector can reclaim it, and the corresponding WeakMap entry is automatically removed. Regular Map holds strong references, keeping keys alive indefinitely.
Q2. Why can WeakMap keys only be objects?
Weak references only make sense for objects managed by the garbage collector. Primitives (strings, numbers, booleans) are value types — they're not garbage-collected in the same way and don't have a distinct identity that could become "unreachable."
Q3. Why is WeakMap not iterable?
Allowing iteration would require the engine to enumerate all keys, which would mean holding strong references to them to prevent GC during iteration — defeating the weak reference semantics. Weak references and iteration are fundamentally incompatible.
Q4. What is a primary use case for WeakMap?
Storing metadata or private state associated with objects without preventing those objects from being garbage-collected. Examples: private class fields, DOM element metadata, memoization caches keyed by objects, tracking listener state per element.
Q5. What is the difference between WeakMap and Map?
Map holds strong references to keys (any type), is iterable, has.size, and is general-purpose. WeakMap holds weak references (object keys only), is not iterable, has no.size, and is specifically for object-associated private data without memory leaks.
Q6. Can you check if a WeakMap has a specific key?
Yes —wm.has(key)works. You can alsoget,set, anddelete. The only missing operations are those requiring enumeration (iteration, size, clear).
Q7. When would you choose a WeakMap over regular Map?
When storing data keyed by objects that have an independent lifecycle (DOM elements, class instances), and you want automatic cleanup when the object is garbage-collected. Regular Map would cause memory leaks by keeping objects alive beyond their useful lifetime.
Key Takeaways
- WeakMap holds weak references to object keys — entries are automatically cleaned up when keys become unreachable.
- Keys must be objects (no primitives) — cannot use strings, numbers, or symbols as keys.
- WeakMap is not iterable — no
forEach,keys(),values(),entries(), orsize. - Best uses: private class data, DOM metadata, memoization caches tied to object lifecycle.
- If you need iteration or primitive keys, use a regular
Mapinstead.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript WeakMap — Weak References, Memory Management Guide.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, data, structures, weakmap
Related JavaScript Master Course Topics