JavaScript Symbol
Symbol is a primitive type in JavaScript that creates guaranteed-unique values. WeakMap and WeakRef allow holding object references without preventing garbage collection — essential for memory-efficient patterns.
// Symbol: always unique
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false — always unique!
console.log(typeof sym1); // 'symbol'
// Symbol as object key (non-enumerable by default)
const id = Symbol('id');
const user = { [id]: 42, name: 'Rahul' };
console.log(user[id]); // 42
console.log(Object.keys(user)); // ['name'] — id hidden!
console.log(JSON.stringify(user)); // {"name":"Rahul"} — id excluded
// Global symbol registry
const s1 = Symbol.for('shared');
const s2 = Symbol.for('shared');
console.log(s1 === s2); // true — same registry entry
// Well-known symbols
class EvenNumbers {
[Symbol.iterator]() {
let n = 0;
return { next: () => ({ value: (n += 2), done: false }) };
}
}
for (const n of new EvenNumbers()) {
if (n > 10) break;
console.log(n); // 2 4 6 8 10
}
WeakMap and WeakSet
// WeakMap: keys must be objects, not primitives
// Keys are weakly held — GC can collect them
const cache = new WeakMap();
function expensiveCompute(obj) {
if (cache.has(obj)) return cache.get(obj);
const result = /* expensive operation */ obj.value * 2;
cache.set(obj, result);
return result;
}
let data = { value: 21 };
expensiveCompute(data); // computed and cached
data = null; // GC can now collect {value:21} AND cache entry
// No memory leak! Regular Map would keep {value:21} alive forever
// WeakSet: store objects without preventing GC
const processed = new WeakSet();
function processOnce(obj) {
if (processed.has(obj)) return;
// do work...
processed.add(obj);
}
WeakRef
// WeakRef: hold reference without preventing GC
class LargeObject { constructor() { this.data = new Array(1e6).fill(0); } }
let obj = new LargeObject();
const ref = new WeakRef(obj);
// Access (may return undefined if GC collected)
const deref = ref.deref();
if (deref) {
console.log('Object still alive');
} else {
console.log('Object was garbage collected');
}
obj = null; // allow GC — ref.deref() may return undefined after this
Q: Why use WeakMap over Map for caching object-related data?
With a regular Map, keys are strongly held — if the key object goes out of scope elsewhere, it cannot be GC'd because the Map still references it (memory leak). WeakMap holds keys weakly, so when no other reference to the key exists, both the key and its Map entry are automatically collected.
Comments (0)
No comments yet. Be the first!
Leave a Comment