Skip to content
Lesson 13 of 15

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

javascript

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:

javascript

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

javascript

Why choose a Map over {}:

  • Keys can be anything: numbers stay numbers (1 and "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 {} is true, while new Map().has("toString") is false.
  • .size is 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.
javascript

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:

javascript

forEach exists too, but calls back with (value, key), which is the reverse of the pair order.

When to use which

NeedUse
Remove duplicates, fast membership testSet
Count or group by arbitrary keysMap
Keys that are objectsMap
Fixed-shape record, JSONplain object

Common mistakes

  • Using an object as a map and getting collisions with constructor, __proto__ or toString.
  • Stringifying a Map or Set and 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 }) is undefined.
  • 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.

Up nextProperty Descriptors and Getters/SettersCollections and Property Descriptors

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…