Map & Set — When a Plain Object Is Not Enough
IntermediateMap allows any value as a key and preserves insertion order; Set stores unique values. Both are the right answer more often than the object-as-dictionary habit suggests.
Overview
For years the only dictionary was a plain object, which forces every key to a string and mixes your data with inherited properties. Map and Set fixed that. Map takes any key including objects and functions, keeps insertion order, reports its size directly, and iterates without prototype surprises. Set gives uniqueness and O(1) membership testing, which turns a common O(n²) filter into O(n). Both also have weak variants that do not prevent garbage collection.
Map vs Object
Use a Map when keys are not fixed strings known at author time, or when you need order and size.
const cache = new Map()
cache.set('key', value)
cache.set(userObject, metadata) // an object as a key — impossible with {}
cache.get('key')
cache.has('key') // no prototype confusion
cache.delete('key')
cache.size // a property, not Object.keys().length
for (const [k, v] of cache) { ... } // insertion order, guaranteed
// The object trap Map avoids:
const obj = {}
obj[1] = 'a'; obj['1'] = 'b'
Object.keys(obj) // ['1'] — the number became a string
const map = new Map()
map.set(1, 'a').set('1', 'b')
map.size // 2 — distinct keysSet for Uniqueness and Membership
The most common use is deduplication, and the second most common is turning a repeated .includes() into a fast lookup.
// Deduplicate
const unique = [...new Set([1, 2, 2, 3])] // [1, 2, 3]
// Fast membership — this is the important one
const allowed = new Set(['admin', 'editor'])
allowed.has(role) // O(1)
// vs the O(n) version inside a loop — O(n*m) overall
users.filter(u => allowedArray.includes(u.role))
users.filter(u => allowed.has(u.role)) // O(n)
// Set operations
const a = new Set([1, 2, 3]), b = new Set([2, 3, 4])
const intersection = [...a].filter(x => b.has(x)) // [2, 3]
const difference = [...a].filter(x => !b.has(x)) // [1]WeakMap and WeakSet
Weak collections hold keys weakly, so an entry does not stop its key being garbage collected. Used for attaching data to objects you do not own.
const metadata = new WeakMap()
function tag(element, info) {
metadata.set(element, info) // when element is removed from the DOM
} // and dereferenced, the entry goes too
// A normal Map here would leak: it holds a strong reference,
// so every element you ever tagged stays in memory forever.
// Constraints: keys must be objects, and they are not iterable
// (you cannot list the contents — that is what makes collection safe).Key Points to Remember
- 1Map accepts any value as a key; object keys are always coerced to strings
- 2Map preserves insertion order, exposes .size, and iterates without prototype pollution
- 3Set gives O(1) membership — replacing .includes() inside a loop turns O(n*m) into O(n)
- 4[...new Set(arr)] is the idiomatic deduplication
- 5WeakMap holds keys weakly so entries do not prevent garbage collection — use it to attach data to DOM nodes
Interview Questions
Sign in to ask AriaWhen would you use a Map instead of a plain object?
How do you remove duplicates from an array?
What problem does WeakMap solve that Map cannot?
Ask Aria about Map & Set — When a Plain Object Is Not Enough
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.