When Objects and Arrays Aren't Quite Right
JavaScript Maps & Sets
`Map` is an object where keys can be anything (not just strings). `Set` is an array with no duplicates. Both have first-class iteration and `size`.
What you'll learn
- Use `Map` for key-value lookups with any key type
- Use `Set` to track unique values
- Know when these beat plain objects and arrays
Map and Set are two collection types built into JavaScript. They
solve specific shortcomings of plain objects and arrays.
Map — Object With Any Key Type
A Map is a key-value collection. Unlike plain objects:
- Keys can be any type — including objects and functions.
- Iteration order is guaranteed to be insertion order.
- Has a
.sizeproperty — noObject.keys(obj).length. - Methods, not bracket syntax:
map.get(key),map.set(key, value).
const ages = new Map();
ages.set("Ada", 36);
ages.set("Lin", 28);
console.log(ages.get("Ada")); // 36
console.log(ages.size); // 2
console.log(ages.has("Tim")); // false
ages.delete("Lin");
console.log(ages.size); // 1 When Map Beats Plain Objects
- Non-string keys:
Mapcan use objects or functions as keys. Plain objects coerce keys to strings.
const meta = new Map();
const ada = { name: "Ada" };
meta.set(ada, "human");
console.log(meta.get(ada)); // "human"
// With a plain object, the key would become "[object Object]" —
// useless for distinguishing different objects. - Frequent additions and removals:
Mapis optimized for it. - You need to know size cheaply.
- You need guaranteed iteration order (objects mostly preserve
insertion order today, but
Mapis explicit about it).
For everyday “structured data” (a user, a config), plain objects are
fine. Reach for Map when keys are dynamic or non-string.
Iterating a Map
Map is iterable — for..of yields [key, value] pairs.
const ages = new Map([
["Ada", 36],
["Lin", 28],
]);
for (const [name, age] of ages) {
console.log(`${name} is ${age}`);
}
// Also: ages.keys(), ages.values(), ages.entries() Set — Array With No Duplicates
A Set stores unique values. Add a value already present and nothing
happens. Order of insertion is preserved.
const colors = new Set();
colors.add("red");
colors.add("green");
colors.add("red"); // ignored — already in
colors.add("blue");
console.log(colors.size); // 3
console.log(colors.has("red")); // true
console.log([...colors]); // ["red", "green", "blue"] The Classic Use: Deduplicate an Array
const tags = ["js", "css", "html", "js", "html"];
const unique = [...new Set(tags)];
console.log(unique); // ["js", "css", "html"] This is the canonical “remove duplicates” pattern in modern JS.
When Set Beats Arrays
- Membership check is O(1) —
set.has(x)is fast.arr.includes(x)is O(n). - You don’t care about duplicates — Set quietly deduplicates.
- You don’t need index-based access.
If you need ordering, indexing, or duplicates, stay with an array.
Cheat Sheet
| Collection | Key type | Best for |
|---|---|---|
| Plain object | string/symbol | Structured records (a user, a config) |
Map | any | Dynamic key-value pairs, especially non-string keys |
| Array | integer index | Ordered lists, when duplicates are OK |
Set | any (unique) | Tracking which values you’ve seen |
Try It Yourself
Exercise
Count unique words
const sentence = "the quick brown fox jumps over the lazy dog the fox";
// your code here
💡 Show hint
✅ Show solution
const sentence = "the quick brown fox jumps over the lazy dog the fox";
const uniqueCount = new Set(sentence.split(" ")).size;
console.log(uniqueCount);
End of Chapter
You now have the full structural toolkit — objects, classes, maps, sets. Next chapter: code that runs over time (async), splits across files (modules), and recovers from failure (errors).
Next chapter: Async, Modules & Errors →