WeakMap is one of JavaScript's most underappreciated data structures. It enables memory-safe patterns that are impossible with regular Maps.
Quick Recap: WeakMap vs Map
WeakMap keys are weakly held — when there are no other references to the key object, both the key and value are garbage collected. This means no memory leaks.
Use Case 1: Private Instance Data
const privateState = new WeakMap();
class Component {
constructor(element) {
privateState.set(this, {
element,
clickCount: 0,
isInitialized: false
});
}
init() {
const state = privateState.get(this);
state.isInitialized = true;
state.element.addEventListener("click", () => {
state.clickCount++;
});
}
}
// When Component instance is GC'd, private state is tooUse Case 2: Memoization with Object Keys
const computeCache = new WeakMap();
function expensiveCompute(obj) {
if (computeCache.has(obj)) return computeCache.get(obj);
const result = /* expensive operation on obj */ obj.data.reduce((a, b) => a + b, 0);
computeCache.set(obj, result);
return result;
}
let data = { data: [1, 2, 3, 4, 5] };
expensiveCompute(data); // Computes
expensiveCompute(data); // Cache hit!
data = null; // Cache entry is automatically cleaned upUse Case 3: DOM Element Metadata
const elementTimers = new WeakMap();
function startTracking(element) {
elementTimers.set(element, {
startTime: performance.now(),
viewCount: 0
});
}
function getTimeOnElement(element) {
const data = elementTimers.get(element);
if (!data) return 0;
return performance.now() - data.startTime;
}
// When element is removed from DOM and GC'd,
// tracking data is automatically cleaned up
// No memory leaks!Use Case 4: Preventing Circular Reference Leaks
// Serialization with circular reference handling
function safeStringify(obj) {
const seen = new WeakSet(); // Not WeakMap, but same principle
return JSON.stringify(obj, (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) return "[Circular]";
seen.add(value);
}
return value;
});
}Use Case 5: Framework Internals
React, Vue, and other frameworks use WeakMaps internally to associate component instances with their fiber/vnode without preventing garbage collection. This is why unmounted components don't leak memory.