demo · v143
WeakMap Counter
DOM elements make ideal WeakMap keys: when the element is removed, the entry can be garbage-collected automatically. WeakMap.prototype.getOrInsert — new in Chrome 143 — collapses the classic has + get + set 0 pattern into a single call. Click any card to increment its per-node counter. Remove cards and the WeakMap cleans itself up; a plain Map would leak them.
0
live nodes
0
total clicks
0
first-visit inserts
0
existing-key hits
// WeakMap: DOM elements as keys → GC-friendly per-node state
const clickCounts = new WeakMap();
cardEl.addEventListener('click', () => {
// getOrInsert: returns existing value OR inserts the default and returns it
const count = clickCounts.getOrInsert(cardEl, 0);
clickCounts.set(cardEl, count + 1);
// getOrInsertComputed: lazily create an object on first access
const meta = metaMap.getOrInsertComputed(cardEl, (el) => ({
id: el.dataset.id,
createdAt: Date.now(),
clicks: 0,
}));
meta.clicks++;
});
// When cardEl is removed from the DOM and no references remain,
// the WeakMap entry is eligible for garbage collection — no manual cleanup.
cardEl.remove();
// Before: every pattern needs has() + get() + set()
const clickCounts = new Map(); // ← Map, not WeakMap: elements never GC'd
cardEl.addEventListener('click', () => {
// Three lines to do what getOrInsert does in one:
if (!clickCounts.has(cardEl)) {
clickCounts.set(cardEl, 0);
}
const count = clickCounts.get(cardEl);
clickCounts.set(cardEl, count + 1);
});
// With Map, we must manually delete entries when nodes are removed,
// or the Map holds a strong reference that prevents GC.
cardEl.remove();
clickCounts.delete(cardEl); // ← easy to forget → memory leak
see also
- Upsert — feature index
- Counter & group-by patterns — Map variants
- Map.getOrInsert(Computed) — basic probe
- ChromeStatus entry
- TC39 upsert proposal