patternjavascriptModeratepending
JavaScript WeakMap and WeakSet for Memory-Safe Caching
Viewed 0 times
WeakMapWeakSetWeakRefgarbage collectionmemory leakcaching
Problem
Using regular Map/Set to cache computed values for objects prevents garbage collection of those objects, causing memory leaks in long-running applications.
Solution
Use WeakMap/WeakSet for object-keyed caches:
WeakRef + FinalizationRegistry (advanced):
// Memory-safe per-object cache
const computeCache = new WeakMap();
function expensiveCompute(obj) {
if (computeCache.has(obj)) {
return computeCache.get(obj);
}
const result = /* expensive operation */ processData(obj);
computeCache.set(obj, result);
return result;
}
// When obj is GC'd, its cache entry is automatically cleaned up
// Track which objects have been processed
const processed = new WeakSet();
function processOnce(node) {
if (processed.has(node)) return;
processed.add(node);
// ... process node
}
// Private data pattern
const privateData = new WeakMap();
class MyClass {
constructor(secret) {
privateData.set(this, { secret });
}
getSecret() {
return privateData.get(this).secret;
}
}WeakRef + FinalizationRegistry (advanced):
const cache = new Map();
const registry = new FinalizationRegistry(key => cache.delete(key));
function getCached(key, compute) {
const ref = cache.get(key);
const val = ref?.deref();
if (val) return val;
const result = compute();
cache.set(key, new WeakRef(result));
registry.register(result, key);
return result;
}Why
Regular Map holds strong references to both keys and values, preventing garbage collection. WeakMap holds weak references to keys, allowing GC when no other references exist.
Gotchas
- WeakMap keys must be objects (not primitives)
- WeakMap is not iterable - you can't list all entries
- WeakRef.deref() may return undefined at any time - always check
Context
Managing memory in long-running JavaScript applications
Revisions (0)
No revisions yet.