Start with the question your collection must answer

An array is a natural choice when order and position matter. But some tasks ask a different question: “Have I seen this value before?” or “What value belongs to this key?” JavaScript provides Set for the first question and Map for the second. Both are available in modern browser consoles and current Node.js environments, so you can try the examples below in either place without installing a package.

A Set stores unique values. A Map stores key–value pairs and lets you retrieve a value by its key. Neither replaces arrays or plain objects everywhere. Choosing a collection based on the operation you perform most often makes the intent clearer and avoids writing repeated search or bookkeeping code.

Use Set to track distinct values

Suppose a list of category names contains repeats. You can write const categories = new Set(['tools', 'guides', 'tools']); and then check categories.size, which is 2. Calling categories.add('news') inserts a new value; calling categories.add('tools') leaves the size unchanged. Use categories.has('guides') to test membership and categories.delete('guides') to remove a value.

To get an array of unique values, write const unique = [...new Set(['red', 'blue', 'red'])];. The result is ['red', 'blue']. A Set iterates in insertion order, so the first occurrence determines where each distinct value appears. This is useful for straightforward deduplication, but it does not sort values or count how often each one occurred.

Uniqueness has an important limit: objects are compared by identity, not by their contents. new Set([{ id: 1 }, { id: 1 }]).size is 2 because the two object literals create separate objects. If you need to deduplicate records by id, track their ids in a Set while processing the records instead of putting the records themselves into a Set.

Use Map when keys lead to values

A Map is useful when each identifier has associated information. For example, const counts = new Map(); counts.set('apple', 2); counts.set('pear', 1); creates two entries. counts.get('apple') returns 2, counts.has('pear') returns true, and counts.size returns 2. Calling set again with an existing key updates its value rather than adding another entry.

A practical pattern is counting items: const counts = new Map(); for (const name of ['apple', 'pear', 'apple']) { counts.set(name, (counts.get(name) ?? 0) + 1); }. The final count for 'apple' is 2. The ?? 0 fallback handles a missing key while preserving an existing value of 0. When a stored value might itself be undefined, use has(key) to distinguish that entry from a missing one; get(key) returns undefined in both cases.

Map keys can also be objects. If const button = {}; then const state = new Map([[button, 'ready']]); allows state.get(button) to return 'ready'. A different object, even one with the same properties, will not retrieve that entry. Keep a reference to an object key for as long as you need to look it up.

Know how iteration and equality behave

You can iterate directly over either collection. for (const value of categories) visits Set values, while for (const [key, value] of counts) visits Map entries as pairs. Both collections preserve insertion order during iteration. Updating the value for an existing Map key does not move that key to a new position; deleting and adding it again does.

Set and Map treat repeated NaN values as the same value, and they treat 0 and -0 as the same key or value. For objects, identity still matters. These rules explain why a Set can remove repeated primitive values but cannot automatically merge separate records that happen to look alike.

Keep arrays and objects when they fit better

Use an array when you need indexed access, a sequence that can contain duplicates, or familiar transformations such as map and filter. Use a plain object when you are describing a record with known property names, such as { name: 'Mira', active: true }. A Map becomes more appealing when keys are added and removed dynamically, when non-string keys matter, or when direct iteration over entries is central to the task.

Before choosing, write down the operation you need: membership suggests Set; lookup by a key suggests Map; position suggests an array; named fields suggest an object. If you must convert a Set to an array, spread it into [...values]. If you need a Map’s entries as an array, use [...entries]. Those conversions make the change of collection type explicit and help keep the rest of the code easy to follow.

Back to category ↗