WeakMap & WeakSet

Hard

WeakMap and WeakSet hold weak references to their keys (WeakMap) or values (WeakSet). A weak reference does not prevent garbage collection — when nothing else references the key object, both the key and its associated value are automatically cleaned up.

Interactive Visualization

Built-in Data Structures

"age":30

Key Points

  • WeakMap keys and WeakSet values must be objects — no primitives
  • Entries are automatically garbage-collected when the key object has no other references
  • Not iterable — no for...of, no .keys(), no .values(), no .entries()
  • No .size property — the runtime cannot know the count since entries may be GC'd at any time
  • WeakMap supports only get, set, has, delete — the minimal API
  • Primary use cases: private data, DOM metadata, caching without memory leaks

Code Examples

Private Data with WeakMap

const privateData = new WeakMap()

class User {
  constructor(name, password) {
    privateData.set(this, { password })
    this.name = name
  }

  checkPassword(attempt) {
    const { password } = privateData.get(this)
    return attempt === password
  }
}

const user = new User('Alice', 'secret123')
console.log(user.name)                 // 'Alice'
console.log(user.password)             // undefined
console.log(user.checkPassword('secret123')) // true

WeakMap stores private data keyed by instance. When the instance is GC'd, the private data goes with it.

DOM Metadata Without Memory Leaks

const elementData = new WeakMap()

function trackElement(element) {
  elementData.set(element, {
    clickCount: 0,
    createdAt: Date.now(),
  })
}

function recordClick(element) {
  const data = elementData.get(element)
  if (data) data.clickCount++
}

// If element is removed from DOM and no references remain,
// the WeakMap entry is automatically garbage collected

When DOM elements are removed, WeakMap entries are cleaned up automatically. A regular Map would cause a memory leak.

Memoization Cache with WeakMap

const cache = new WeakMap()

function expensiveComputation(obj) {
  if (cache.has(obj)) return cache.get(obj)

  const result = Object.keys(obj).length * 100
  cache.set(obj, result)
  return result
}

let data = { a: 1, b: 2, c: 3 }
expensiveComputation(data) // computes
expensiveComputation(data) // cached

data = null // cache entry eligible for GC

WeakMap-based caches self-clean when cached objects are no longer used.

WeakSet for Object Tagging

const visited = new WeakSet()

function processNode(node) {
  if (visited.has(node)) return
  visited.add(node)
  console.log('Processing:', node.id)
}

const nodeA = { id: 'A' }
processNode(nodeA) // 'Processing: A'
processNode(nodeA) // skipped

WeakSet is ideal for tagging objects without preventing their garbage collection.

Common Mistakes

  • Trying to use primitive values as WeakMap keys — only objects are allowed
  • Attempting to iterate over a WeakMap/WeakSet — they have no iteration methods
  • Using WeakMap when you need to enumerate entries — use a regular Map
  • Expecting .size to exist — the runtime cannot report size

Interview Tips

  • Explain the GC benefit: WeakMap/WeakSet prevent memory leaks
  • Know the API limitations: not iterable, no size, keys must be objects
  • Give concrete use cases: private class data, DOM metadata, caching
  • Compare with Map/Set: weak variants trade enumeration for automatic memory management

Related Concepts