Sets and Maps in JavaScript

Store unique values with Set, key-value pairs with any type of key with Map, remove duplicates, count things, and know when to use them instead of arrays and objects.

Lesson 30 of 56Intermediate16 min read

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

JavaScript
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
MethodDoes
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
sizeNumber of values (a property, not a method)

Removing duplicates and set operations

The most popular use of Set is removing duplicates:

JavaScript
const unique = [...new Set([3, 1, 3, 2, 1])]; // [3, 1, 2]

Sets also support set maths, now built into all modern browsers:

MethodResult
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

JavaScript
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
ObjectMap
Key typesStrings and symbols onlyAnything: objects, elements, numbers
OrderMostly insertion order, with exceptionsAlways insertion order
SizeObject.keys(obj).lengthmap.size
LoopingNeeds Object.entriesDirectly iterable
Best forFixed records like { name, age }, and JSONLookups 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

JavaScript
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 Map

Both 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 Set stores unique values; has checks membership quickly.
  • [...new Set(array)] removes duplicates in one line.
  • A Map stores key-value pairs with keys of any type, in insertion order.
  • Use get, set, has, delete and size with 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.

Example 1

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)));
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 2Duplicates disappear as the set is built.
  2. Line 4Spread turns the set back into an array.
  3. Lines 9 to 12A set is perfect for on/off states like likes or selected items.
  4. Line 17Values in both sets, written in a way every browser supports.
Example 2

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));
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 5Read the current count (or 0) and add one.
  2. Line 11Spread the map into [key, value] pairs and sort by count.
  3. Line 14Object.fromEntries converts it to a plain object, ready for JSON.
Example 3

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));
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 5 to 6Map keys can be the objects themselves.
  2. Line 7Looking up ana returns her own value.
  3. 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

Don't
mySet.length;  // undefined
myMap.size();  // TypeError: not a function
Do
mySet.size;
myMap.size;

Using square brackets on a Map

Don't
const m = new Map();
m["tea"] = 2; // sets an ordinary property, not a Map entry
m.get("tea"); // undefined
Do
m.set("tea", 2);
m.get("tea"); // 2

Expecting Set to remove duplicate objects

Don't
new Set([{ id: 1 }, { id: 1 }]).size; // 2: different objects
Do
const 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.

Fill in the blankseasy

Remove the duplicates from the array.

const ids = [4, 4, 7, 2, 7];
const unique = [...new (ids)];
console.log(unique);
Predict the outputmedium

What is logged?

const s = new Set("banana");
console.log(s.size, [...s].join(""));
Multiple choiceeasy

Which method reads a value from a Map?

Multiple choicemedium

When is a Map a better choice than an object?

Fix the bugmedium

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);
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Counts repeats
  • Counts single items
  • Size is the number of different items

JavaScript Sets and Maps Quiz

5 questions to check what you learned.

  1. 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
  2. How do you get the number of entries in a Map?

    • map.length
    • map.count()
    • map.size
    • Object.keys(map).length
  3. What order does a Map keep its entries in?

    • Alphabetical
    • Random
    • By value
    • The order they were added
  4. How do you turn a Map into a plain object?

    • JSON.parse(map)
    • Object.fromEntries(map)
    • map.toObject()
    • { ...map }
  5. 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 }:

  1. Return a Map where each key is a class name
  2. Each value is an array of names in that class, in the order they appear
  3. 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));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Returns a Map
  • Groups names in order
  • Unique classes
  • Uses a Set