Arrays and objects can hold almost anything, but they aren't always the best fit. Want a list where every value appears only once, such as the tags on a blog or the IDs of products in a wish list? An array lets duplicates in, and checking for them gets slow as the list grows. Want to look things up by a key that isn't a string, such as a DOM element or an object? Plain objects turn every key into a string.
JavaScript has two collections built for these jobs. A Set stores unique values: add the same thing twice and it's only stored once, and checking whether a value is present is very fast. A Map stores key-value pairs like an object, but its keys can be any type, it remembers the order you added them, and it has a handy size.
In this lesson you'll learn the methods of both, the one-line trick for removing duplicates from an array, how to count things with a Map, how to loop over them, and how they compare with arrays and objects. You'll also meet their memory-friendly cousins, WeakMap and WeakSet.
Set: unique values
const tags = new Set(["css", "html"]);
tags.add("js");
tags.add("css"); // ignored, already there
tags.has("html"); // true
tags.delete("html");
tags.size; // 2| Method | Does |
|---|---|
new Set(iterable) | Creates a set, optionally from an array or string |
add(value) | Adds a value (returns the set, so calls can be chained) |
has(value) | Checks for a value, very quickly |
delete(value) | Removes a value, returns true if it was there |
clear() | Removes everything |
size | Number of values (a property, not a method) |
Removing duplicates and set operations
The most popular use of Set is removing duplicates:
const unique = [...new Set([3, 1, 3, 2, 1])]; // [3, 1, 2]Sets also support set maths, now built into all modern browsers:
| Method | Result |
|---|---|
a.union(b) | Everything in either |
a.intersection(b) | Only what's in both |
a.difference(b) | In a but not b |
a.isSubsetOf(b) | Is everything in a also in b? |
Values are compared like ===, so two different objects with the same contents count as two values.
Map: key-value pairs with any key
const prices = new Map();
prices.set("tea", 2.2).set("cake", 3.5);
prices.get("tea"); // 2.2
prices.has("coffee"); // false
prices.size; // 2| Object | Map | |
|---|---|---|
| Key types | Strings and symbols only | Anything: objects, elements, numbers |
| Order | Mostly insertion order, with exceptions | Always insertion order |
| Size | Object.keys(obj).length | map.size |
| Looping | Needs Object.entries | Directly iterable |
| Best for | Fixed records like { name, age }, and JSON | Lookups and counts that change often |
Use objects for structured records and data you'll send as JSON. Use a Map when keys are added and removed at runtime, or aren't strings.
Looping and converting
for (const value of mySet) { }
for (const [key, value] of myMap) { }
myMap.forEach((value, key) => { });
const arr = [...mySet]; // Set to array
const obj = Object.fromEntries(myMap); // Map to object
const map = new Map(Object.entries(obj)); // object to MapBoth collections keep insertion order, so loops visit items in the order they were added. map.keys(), map.values() and map.entries() give iterators for each part.
JavaScript Sets and Maps Syntax
Set and Map
const s = new Set([1, 2]);
s.add(3); s.has(2); s.delete(1); s.size;
const unique = [...new Set(list)];
const m = new Map([["a", 1]]);
m.set("b", 2); m.get("a"); m.has("b"); m.delete("a"); m.size;
for (const [key, value] of m) { }
const counts = new Map();
counts.set(word, (counts.get(word) ?? 0) + 1);JavaScript Sets and Maps Summary
- A
Setstores unique values;haschecks membership quickly. [...new Set(array)]removes duplicates in one line.- A
Mapstores key-value pairs with keys of any type, in insertion order. - Use
get,set,has,deleteandsizewith Maps. - Use objects for fixed records and JSON; use Maps for dynamic lookups and counts.
JavaScript Sets and Maps Examples
Each example runs in the page. Edit the code and press Run to see what changes.
Unique values with Set
const visits = ["home", "shop", "home", "cart", "shop", "home"];
const pages = new Set(visits);
console.log("Unique pages:", [...pages]);
console.log("How many:", pages.size);
console.log("Visited cart?", pages.has("cart"));
const liked = new Set();
function toggleLike(id) {
liked.has(id) ? liked.delete(id) : liked.add(id);
return [...liked];
}
console.log(toggleLike(7), toggleLike(9), toggleLike(7));
const a = new Set(["html", "css", "js"]);
const b = new Set(["js", "python"]);
console.log("Both:", [...a].filter(x => b.has(x)));Line-by-line explanation
- Line 2Duplicates disappear as the set is built.
- Line 4Spread turns the set back into an array.
- Lines 9 to 12A set is perfect for on/off states like likes or selected items.
- Line 17Values in both sets, written in a way every browser supports.
Counting words with a Map
const text = "the cat and the hat and the bat";
const counts = new Map();
for (const word of text.split(" ")) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
console.log("the:", counts.get("the"));
console.log("Different words:", counts.size);
const sorted = [...counts].sort((a, b) => b[1] - a[1]);
console.log("Top two:", sorted.slice(0, 2));
console.log("As an object:", Object.fromEntries(counts));Line-by-line explanation
- Line 5Read the current count (or 0) and add one.
- Line 11Spread the map into
[key, value]pairs and sort by count. - Line 14
Object.fromEntriesconverts it to a plain object, ready for JSON.
Objects as keys
const ana = { name: "Ana" };
const ben = { name: "Ben" };
const lastSeen = new Map();
lastSeen.set(ana, "09:15");
lastSeen.set(ben, "11:40");
console.log(ana.name, "was last seen at", lastSeen.get(ana));
const plain = {};
plain[ana] = "09:15";
plain[ben] = "11:40";
console.log("Object keys:", Object.keys(plain));Line-by-line explanation
- Lines 5 to 6Map keys can be the objects themselves.
- Line 7Looking up
anareturns her own value. - Lines 10 to 12An object turns both keys into the same string, "[object Object]", so Ben overwrites Ana.
Common JavaScript Sets and Maps Mistakes
Using size() or length
mySet.length; // undefined
myMap.size(); // TypeError: not a functionmySet.size;
myMap.size;Using square brackets on a Map
const m = new Map();
m["tea"] = 2; // sets an ordinary property, not a Map entry
m.get("tea"); // undefinedm.set("tea", 2);
m.get("tea"); // 2Expecting Set to remove duplicate objects
new Set([{ id: 1 }, { id: 1 }]).size; // 2: different objectsconst unique = [...new Map(items.map(i => [i.id, i])).values()];To remove duplicates by a property, key a Map by that property.
JavaScript Sets and Maps in Real Projects
Sets and Maps in real code
Shopping sites store selected filter options in a Set. Chat apps track online user IDs in a Set for instant lookups. Caches map request URLs to responses with a Map. Frameworks attach data to DOM nodes with WeakMaps, and analytics code counts events with a Map before sending totals to the server.
JavaScript Sets and Maps Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Remove the duplicates from the array.
const ids = [4, 4, 7, 2, 7];
const unique = [...new (ids)];
console.log(unique);
What is logged?
const s = new Set("banana");
console.log(s.size, [...s].join(""));Which method reads a value from a Map?
When is a Map a better choice than an object?
tally(items) should return a Map of each item to how many times it appears. Fix the bugs.
function tally(items) {
const counts = new Map();
for (const item of items) {
counts[item] = counts.get(item) + 1;
}
return counts;
}
const t = tally(["a", "b", "a"]);
console.log(t.get("a"), t.size);- Counts repeats
- Counts single items
- Size is the number of different items
JavaScript Sets and Maps Quiz
5 questions to check what you learned.
What happens when you add a value that's already in a Set?
- An error
- It's stored twice
- The old one is removed
- Nothing, it's ignored
How do you get the number of entries in a Map?
- map.length
- map.count()
- map.size
- Object.keys(map).length
What order does a Map keep its entries in?
- Alphabetical
- Random
- By value
- The order they were added
How do you turn a Map into a plain object?
- JSON.parse(map)
- Object.fromEntries(map)
- map.toObject()
- { ...map }
Why is WeakMap useful for data attached to DOM elements?
- Entries disappear automatically when the element is no longer used, avoiding memory leaks
- It's faster to loop over
- It accepts string keys
- It can be saved as JSON
JavaScript Sets and Maps Challenge
Group students by class
Write groupByClass(students) where each student is { name, className }:
- Return a Map where each key is a class name
- Each value is an array of names in that class, in the order they appear
- Also write
allClasses(students)that returns an array of the unique class names, using a Set
function groupByClass(students) {
}
function allClasses(students) {
}
const students = [
{ name: "Ana", className: "7A" },
{ name: "Ben", className: "7B" },
{ name: "Cai", className: "7A" },
];
console.log(groupByClass(students).get("7A"), allClasses(students));- Returns a Map
- Groups names in order
- Unique classes
- Uses a Set