Map and Set
Learn how the Map and Set data structures work in JavaScript — storing key-value pairs with any type of key, and storing collections of guaranteed-unique values.
Reading Time
16 min
Lesson
Lesson 44 of 48
Beyond Objects and Arrays
Plain objects and arrays cover most everyday needs, but they each have limitations. Object keys are always coerced to strings (or symbols), so you can't use an object or a number as a truly distinct key. Arrays can hold duplicate values freely, even when you specifically want a collection where every value only appears once. Map and Set are built-in data structures designed to solve exactly these two problems.
What Is a Map?
A Map stores key-value pairs, just like a plain object — but unlike an object, a Map's keys can be any value at all: a string, a number, a function, another object, even NaN. Keys also keep their original type instead of being converted to strings, and a Map remembers the order in which entries were inserted, which it reliably preserves during iteration.
Creating a Map
Console Output
Click “Run” to see the console output here.
Core Map Methods
A Map's essential operations are small and consistent: set(key, value) adds or updates an entry (and returns the Map itself, so calls can be chained), get(key) retrieves a value, has(key) checks whether a key exists, delete(key) removes an entry, and the size property (not a method — no parentheses) tells you how many entries the Map holds.
set / get / has / delete / size
Console Output
Click “Run” to see the console output here.
Iterating a Map
Maps are iterable, so you can use a for...of loop directly, which yields [key, value] pairs you can destructure. Map also exposes .keys(), .values(), and .entries() if you only need one part of each pair, and .forEach() as a callback-based alternative — entries are always visited in the order they were inserted.
Looping Over a Map
Console Output
Click “Run” to see the console output here.
What Is a Set?
A Set is a collection of values where every value is guaranteed to be unique — adding a value that's already present has no effect. Like a Map, a Set can hold any type of value, preserves insertion order during iteration, and checks for equality using the same rules as strict equality (with the one exception that NaN is treated as equal to itself inside a Set).
Creating a Set
Console Output
Click “Run” to see the console output here.
Core Set Methods
A Set's API mirrors a Map's closely: add(value) inserts a value (and returns the Set, so calls can be chained), has(value) checks membership, delete(value) removes a value, and size reports how many unique values the Set currently holds.
add / has / delete / size
Console Output
Click “Run” to see the console output here.
Using a Set to Dedupe an Array
Because a Set automatically discards duplicate values, converting an array to a Set and back is a short, common way to remove duplicates while preserving the original order of first appearance. Spreading a Set into a new array (or passing it to Array.from()) turns it back into a regular array you can use every array method on.
Deduping an Array with a Set
Console Output
Click “Run” to see the console output here.
Map / Set vs. Object / Array
| Structure | Reach for it when... |
|---|---|
| Map | You need keys that are not strings, frequent additions/removals, or guaranteed insertion order |
| Object | You have a fixed, known set of string-keyed properties and want simple dot-notation access |
| Set | You need a collection where every value must be unique, and fast membership checks |
| Array | You need an ordered list that may contain duplicates, with rich built-in iteration methods |
When to Reach for Map/Set Over Object/Array
Prefer a Map over a plain object when keys aren't simple strings, when keys are decided at runtime and could accidentally collide with built-in object properties (like "toString"), or when you'll be adding and removing entries frequently and want a reliable size property. Prefer a Set over an array when uniqueness matters and you'll be checking membership often — has() on a Set is much faster than repeatedly calling includes() on a large array.
Maps and Sets Are Not JSON-Friendly by Default
JSON.stringify() does not know how to serialize a Map or a Set — it will produce an empty object {} for a Map and an empty object {} for a Set, silently losing your data. If you need to persist or transmit one, convert it to a plain array or object first (for example, [...someMap.entries()] or [...someSet]) before stringifying.