What are WeakMap and WeakSet used for in JavaScript?

Advanced14 min interview
Skills tested:
What weak references are and how they differ from strong referencesWeakMap: object-keyed metadata store that does not prevent GCWeakSet: object membership tracking without preventing collectionWhy WeakMap and WeakSet do not support iteration or sizePractical use cases: private data, caching, and DOM node metadata

Advertisement

🧩 Scenario

In a real codebase, WeakMap is used to associate metadata or private state with objects without preventing those objects from being garbage collected when they fall out of use. Libraries and frameworks use this pattern to attach component state, event handler registries, or validation rules to DOM nodes without creating memory leaks.

Architecture Walkthrough

Strong vs Weak References

A regular reference (the kind you get when you assign an object to a variable or store it in a Map key) is a strong reference. The garbage collector will not collect an object as long as any strong reference to it exists. A weak reference does not count toward reachability. An object with only weak references pointing to it is treated by the GC as unreachable and eligible for collection.

WeakMap and WeakSet hold weak references to their keys and members respectively. If the only remaining reference to an object is its role as a WeakMap key, the GC can collect the object and the WeakMap entry disappears automatically.

WeakMap: Object-Keyed Metadata

WeakMap accepts only objects as keys (not primitives). Values can be anything. Its primary use case is associating additional data with an object without controlling that object's lifecycle. A library that needs to attach state to a user-provided DOM node can use a WeakMap with the node as the key. When the node is removed from the document and all other references to it are dropped, the GC collects the node and the WeakMap entry evaporates without any manual cleanup.

WeakMap does not expose .size, .keys(), .values(), .entries(), or forEach(). These operations are intentionally absent because the entries can disappear at any GC cycle. An enumeration that might return different results every time the GC runs would be non-deterministic and misleading.

WeakSet: GC-Friendly Membership Tracking

WeakSet stores a collection of objects with the same GC-friendly property: membership does not prevent the object from being collected. Its API is minimal: add, has, delete. Like WeakMap, it has no size and no iteration. The canonical use case is tracking which objects have been visited or processed without keeping those objects alive just for the sake of the tracking set.


Key Code Explained

// WeakMap: attach metadata to objects without holding strong references
const domCache = new WeakMap();

function processNode(node) {
  if (domCache.has(node)) {
    return domCache.get(node); // return cached result
  }
  const result = computeExpensiveLayout(node);
  domCache.set(node, result);
  return result;
}

// When node is removed from the DOM and all other references drop:
// - GC collects the node
// - The WeakMap entry is automatically removed
// - No manual cache.delete(node) needed

// Compare with Map: node stays alive as long as the Map exists
const strongCache = new Map();
strongCache.set(node, computeExpensiveLayout(node));
// node is retained by strongCache even after removal from the DOM

// Private data pattern using WeakMap (pre-private class fields)
const _private = new WeakMap();

class Counter {
  constructor(start) {
    _private.set(this, { count: start });
  }
  increment() {
    _private.get(this).count++;
  }
  value() {
    return _private.get(this).count;
  }
}

const c = new Counter(0);
c.increment();
c.value(); // 1
// _private.get(c).count is inaccessible from outside the module

// WeakSet: track processed objects without keeping them alive
const processed = new WeakSet();

function process(request) {
  if (processed.has(request)) {
    throw new Error('Request already processed');
  }
  processed.add(request);
  // handle request...
  // When request is done and all references drop, GC collects it
  // and processed.has(request) becomes irrelevant
}

The domCache example is the most practical demonstration. A Map with DOM node keys holds strong references that keep the nodes alive indefinitely, even after they are removed from the page. The WeakMap version requires no manual cleanup because the GC handles eviction automatically when the node is no longer reachable.


Tradeoffs

StructureKey typePrevents GC of keyIterableHas .size
MapAny valueYes (strong ref)YesYes
WeakMapObjects onlyNo (weak ref)NoNo
SetAny valueYes (strong ref)YesYes
WeakSetObjects onlyNo (weak ref)NoNo

What Interviewers Actually Check

  • Whether you can explain what a weak reference is and how it differs from a strong reference
  • Whether you know that WeakMap keys must be objects, not primitives
  • Whether you know why WeakMap and WeakSet do not support iteration or .size
  • Whether you can describe a real use case that demonstrates the GC benefit
  • Whether you know the difference between using Map vs WeakMap for caching object metadata

Follow-Up Questions

  1. How does WeakRef differ from WeakMap in terms of how you access the weakly held value?
  2. What is FinalizationRegistry and how does it let you run cleanup code when a weakly held object is collected?
  3. How do modern private class fields (#field) compare to the WeakMap private data pattern?
  4. If a WeakMap entry disappears because the key was collected, is there any way to observe when this happened?
  5. Can you use a WeakMap to implement a simple memoize function? What are the limitations compared to a Map-based version?

Common Candidate Mistakes

  • Trying to use a string or number as a WeakMap key and not understanding why it throws
  • Trying to call .size on a WeakMap or looping over it and not knowing why these operations do not exist
  • Using a Map with object keys in a cache that accumulates entries over the page lifetime, causing the referenced objects to never be collected
  • Thinking the value in a WeakMap entry is what is weakly held when it is actually the key that is held weakly
  • Not knowing about WeakRef and FinalizationRegistry as more granular weak reference tools added in ES2021

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you explain the difference between a strong reference and a weak reference?
  • Can you explain why using an object as a WeakMap key does not prevent GC of that object?
  • Can you describe a real use case for WeakMap such as private data or per-object caching?
  • Can you explain why .size and iteration are not available on WeakMap and WeakSet?
  • Can you describe a scenario where Map would be wrong and WeakMap is the correct choice?

Summary

WeakMap and WeakSet hold their keys and members with weak references, meaning those references do not count toward an object's reachability for garbage collection. When an object used as a WeakMap key has no strong references remaining, the GC can collect it and the WeakMap entry disappears automatically without any explicit cleanup.

The consequence is that WeakMap and WeakSet cannot support iteration, .size, or enumeration. The contents are non-deterministic from the GC's perspective: entries may vanish between one GC cycle and the next. The API is intentionally limited to get, set, has, and delete for WeakMap, and add, has, and delete for WeakSet.

The practical pattern for WeakMap is associating metadata or cached computation results with objects (often DOM nodes or class instances) without controlling the lifecycle of those objects. When the object is no longer needed by the rest of the application, the WeakMap entry is cleaned up for free by the GC rather than requiring manual eviction.

Related Videos
Watch these videos to learn more about this topic
Frequently Asked Questions

Why can't I iterate over WeakMap or WeakSet?

Because their entries can disappear at any time due to garbage collection, so iteration results would be non-deterministic.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement