Advanced 3 min · March 17, 2026

WeakMap in Production — Preventing DOM Node Memory Leaks

WeakMap and WeakSet allow GC to reclaim DOM keys, avoiding memory leaks in long-running SPAs.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
Quick Answer

WeakMap and WeakSet hold weak references to their keys/values — if no other reference to the object exists, it can be garbage collected even if it is in a WeakMap or WeakSet. This makes them ideal for caching data associated with objects without preventing those objects from being collected. Limitation: they are not iterable.

WeakMap — Object-keyed Private Data

ExampleJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const privateData = new WeakMap();

class Person {
    constructor(name, age) {
        // Store private data keyed by this instance
        privateData.set(this, { age, secretCode: Math.random() });
        this.name = name;  // public
    }

    getAge() {
        return privateData.get(this).age;  // private data not on the object
    }

    greet() {
        return `Hi, I'm ${this.name}, age ${this.getAge()}`;
    }
}

const alice = new Person('Alice', 30);
console.log(alice.greet());      // Hi, I'm Alice, age 30
console.log(alice.age);          // undefined — not a public property
console.log(alice.secretCode);   // undefined — truly private

// When alice goes out of scope and is GC'd, privateData entry is also collected
Output
Hi, I'm Alice, age 30
undefined
undefined

WeakMap vs Map for Caching

ExampleJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Problem: regular Map prevents garbage collection of DOM nodes
const cache = new Map();

function processElement(el) {
    if (cache.has(el)) return cache.get(el);
    const result = expensiveComputation(el);
    cache.set(el, result);
    return result;
}
// If el is removed from the DOM, cache still holds a reference → memory leak

// Solution: WeakMap — entry removed when el is GC'd
const weakCache = new WeakMap();

function processElementSafe(el) {
    if (weakCache.has(el)) return weakCache.get(el);
    const result = { processed: true, timestamp: Date.now() };
    weakCache.set(el, result);
    return result;
}

// Keys must be objects — not primitives
const obj = {};
weakCache.set(obj, 'data');   // OK
// weakCache.set('string', 'data');  // TypeError: Invalid value used as weak map key

function expensiveComputation(el) { return { computed: true }; }
Output
WeakMap entries GC'd automatically when key objects are no longer reachable

WeakSet — Tracking Object Membership

ExampleJAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const visited = new WeakSet();

function processNode(node) {
    if (visited.has(node)) {
        console.log('Already processed, skipping');
        return;
    }
    visited.add(node);
    console.log('Processing node:', node.id);
    // process...
}

const nodeA = { id: 'a', data: 'hello' };
const nodeB = { id: 'b', data: 'world' };

processNode(nodeA);  // Processing node: a
processNode(nodeA);  // Already processed, skipping
processNode(nodeB);  // Processing node: b

// WeakSet only has: add(), has(), delete()
// No size, no iteration — by design (GC timing is unpredictable)
Output
Processing node: a
Already processed, skipping
Processing node: b

Key takeaways

1
WeakMap and WeakSet hold weak references
objects can be garbage collected even when held as keys.
2
Keys must be objects (or registered symbols in WeakMap)
primitives are not allowed.
3
Neither is iterable
no .forEach(), no .keys(), no .size. This is intentional.
4
Primary use case
caching metadata about objects without preventing their collection.
5
WeakRef and FinalizationRegistry (ES2021) are the more explicit tools if you need to react to GC.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

FAQ · 2 QUESTIONS

Frequently Asked Questions

01
When should I use WeakMap over Map?
02
Why can't WeakMap and WeakSet be iterated?
🔥

That's Advanced JS. Mark it forged?

3 min read · try the examples if you haven't

Previous
Symbol and BigInt in JavaScript
12 / 27 · Advanced JS
Next
Generators in JavaScript