All topics
Objectsintermediate

Map and Set vs Plain Objects and Arrays

The dedicated key-value and unique-value collection types, and why they're often better choices than objects and arrays for certain use cases.

Map and Set are purpose-built collections. Each fixes specific limitations of the object and array they replace.

A plain object used as a map is like using sticky notes labeled with only single words stuck to a corkboard that came with some notes already pre-stuck on it (inherited prototype properties) — a Map is a purpose-built filing cabinet with labeled drawers that accepts any kind of label, including photographs (objects) as labels, and comes completely empty to start.

Key Concepts

1
Map against an object.
    keys         any type, including objects and functions
                 (object keys are strings or symbols only)
    order        insertion order, always
                 (objects put integer-like keys first)
    size         map.size
                 (Object.keys(o).length -- builds an array)
    iteration    directly iterable
    prototype    no inherited keys to collide with
Map
2
    const m = new Map();
    m.set(userObject, 'metadata');    // an object as a key
    m.get(userObject);
3
Object keys being strings is the one that bites.
    const o = {};
    o[1] = 'a';
    o['1'] = 'b';
    o[1];          // 'b' -- the same key
4
    const m = new Map();
    m.set(1, 'a').set('1', 'b');
    m.get(1);      // 'a' -- different keys
5
Set against an array.
    uniqueness   guaranteed
    has()        O(1)
                 (array.includes is O(n))
Set
6
    const seen = new Set();
    if (!seen.has(id)) seen.add(id);
7
    [...new Set(arr)]     // deduplicate an array
8
The performance difference is real at scale. Checking membership in a 100,000-element array with includes scans it; a Set hashes.
includesSet
9
When a plain object is still right.
    JSON              objects serialise; Map does not
    fixed shape       a record with known fields
    destructuring     const { a, b } = obj
10
JSON.stringify(map) gives {}, which is the main reason Maps do not appear in API payloads.
JSON.stringify(map){}
11
Weak versions, for a specific job.
    WeakMap, WeakSet
12
Keys must be objects, and they do not prevent garbage collection. So metadata attached to a DOM node in a WeakMap disappears when the node does — where a Map would keep it alive forever.
WeakMapMap
13
That is the leak they exist to prevent, and it is why caches keyed by object use WeakMap.
WeakMap
14
The rule of thumb. A Map when keys are dynamic, non-string, or order matters. A Set for membership and deduplication. An object for a record with a known shape, and for anything that must be JSON.
MapSet
15
What the interviewer is probing.1. "When would you choose a Map over an object?" Probing: the properties. Stalls: "They are the same." Moves up: non-string keys, frequent additions and deletions, a reliable size, and guaranteed insertion order.
16
2. "What does a WeakMap give you?" Probing: the garbage collection property. Stalls: "A smaller map." Moves up: keys held weakly, so an entry disappears when the key object is collected — which is how you attach metadata without leaking.
17
3. "How do you deduplicate an array?" Probing: the idiom. Stalls: "Filter with indexOf." Moves up: [...new Set(arr)], which is linear rather than quadratic.
18
4. "What is the cost of using an object as a map?" Probing: the pitfalls. Stalls: "None." Moves up: prototype keys can collide, every key becomes a string, and there is no size without counting.