Step 1 of 7 · Reading · ~3 min
Learn
Collections and Property Descriptors
Set, Map, and the Iteration Protocols
Plain objects and arrays can imitate a dictionary or a set of unique values, with sharp edges. Set and Map are built for those jobs. By the end of this lesson you can use both, say when each beats an object or array, and rely on their one special promise: they remember the order things went in.
Set: each value once
new Set(array) drops repeats, so [...new Set(list)] is the standard way to de-duplicate. Sets have no set algebra built in, but it takes one line with an array method:
has is fast however big the set is, unlike array.includes, which scans. Sets compare with SameValueZero: like ===, except NaN equals NaN, so new Set([NaN, NaN]).size is 1. Objects are compared by reference, never by content.
Map: a dictionary with any key
Why choose a Map over {}:
- Keys can be anything: numbers stay numbers (
1and"1"are different keys, but both become"1"in an object), and an object works as a key, matched by reference. - No inherited keys:
"toString" in {}istrue, whilenew Map().has("toString")isfalse. .sizeis a property, and iteration is straightforward and ordered.
Keep a plain object for fixed-shape records and anything that must become JSON: JSON.stringify(new Map(...)) is {}. Convert first with Object.fromEntries(map), and back with new Map(Object.entries(obj)).
Order is part of the contract
Set and Map iterate in insertion order: the order in which keys were first added. Two rules decide where a key sits:
- Setting a key that already exists changes its value but keeps its position.
- Deleting a key and adding it again puts it at the end.
The first key is [...m.keys()][0], or m.keys().next().value without building an array.
Iterating
Anything with a [Symbol.iterator]() method works with for...of, spread, destructuring and Array.from (the iterators lesson). A Map iterates as [key, value] pairs, so you destructure them:
forEach exists too, but calls back with (value, key), which is the reverse of the pair order.
When to use which
| Need | Use |
|---|---|
| Remove duplicates, fast membership test | Set |
| Count or group by arbitrary keys | Map |
| Keys that are objects | Map |
| Fixed-shape record, JSON | plain object |
Common mistakes
- Using an object as a map and getting collisions with
constructor,__proto__ortoString. - Stringifying a
MaporSetand getting{}. - Comparing two Sets with
===. It compares references, not contents. - Looking up an object key with a new but equal-looking object:
m.get({ id: 1 })isundefined. - Forgetting that updating a key does not change its position in the order.
Your exercise
Use the ordering rules above as a tool. The starter wraps a Map in a small class with a capacity, and you write the two methods that keep the map in the right order.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…