JavaScript course menu
JavaScript Map and Set: When to Use Them Instead of Objects and Arrays
Learn JavaScript Map and Set: creating Maps, get, set, has and delete, any type of key, iteration order and size, Map vs object; Sets for unique values, removing duplicates, set operations, and WeakMap and WeakSet.
On this page
Objects and arrays cover most needs, but two built-in collections are better for specific jobs: Map for key-value data that changes often or needs non-string keys, and Set for collections of unique values.
Map#
A Map stores key-value pairs, like an object, with a clearer API:
const stock = new Map();
stock.set("pens", 40);
stock.set("notebooks", 12);
stock.set("pens", 35); // updates the existing key
console.log(stock.get("pens"));
console.log(stock.has("erasers"));
console.log(stock.size);
stock.delete("notebooks");
console.log(stock);35
false
2
Map(1) { 'pens' => 35 }Creating from pairs and looping#
const prices = new Map([
["tea", 20],
["coffee", 35],
]);
for (const [drink, price] of prices) {
console.log(`${drink}: ₹${price}`);
}
console.log([...prices.keys()]);
console.log(Object.fromEntries(prices));tea: ₹20
coffee: ₹35
[ 'tea', 'coffee' ]
{ tea: 20, coffee: 35 }Maps remember insertion order, and are iterable, so for...of works directly.
Any type of key#
Object keys are always strings (or symbols). Map keys can be anything, including objects:
const asha = { name: "Asha" };
const ravi = { name: "Ravi" };
const lastSeen = new Map();
lastSeen.set(asha, "10:30");
lastSeen.set(ravi, "11:05");
console.log(lastSeen.get(asha));
const obj = {};
obj[asha] = "10:30";
console.log(Object.keys(obj));10:30
[ '[object Object]' ]Using an object as a key in a plain object turns it into the string "[object Object]", so every object would collide. A Map keeps them separate.
Map or object?#
Counting with a Map:
const words = "the cat and the hat and the bat".split(" ");
const counts = new Map();
for (const w of words) {
counts.set(w, (counts.get(w) ?? 0) + 1);
}
console.log(counts);Map(5) { 'the' => 3, 'cat' => 1, 'and' => 2, 'hat' => 1, 'bat' => 1 }Set#
A Set holds unique values: adding something it already contains does nothing:
const tags = new Set();
tags.add("html");
tags.add("css");
tags.add("html");
console.log(tags);
console.log(tags.size);
console.log(tags.has("css"));
tags.delete("css");
console.log([...tags]);Set(2) { 'html', 'css' }
2
true
[ 'html' ]Removing duplicates#
The most common use of a Set:
const visits = ["home", "about", "home", "blog", "about", "home"];
const unique = [...new Set(visits)];
console.log(unique);[ 'home', 'about', 'blog' ]has on a Set is much faster than includes on a large array, so Sets are also good for "have I seen this before?" checks.
Set operations#
const frontend = new Set(["html", "css", "javascript"]);
const backend = new Set(["javascript", "sql", "python"]);
const both = [...frontend].filter((x) => backend.has(x));
const all = new Set([...frontend, ...backend]);
const onlyFrontend = [...frontend].filter((x) => !backend.has(x));
console.log(both);
console.log(all.size);
console.log(onlyFrontend);[ 'javascript' ]
5
[ 'html', 'css' ]Newer versions of JavaScript (ES2025) also add built-in methods such as a.intersection(b), a.union(b) and a.difference(b), available in current browsers and Node.js 22 and later.
WeakMap and WeakSet#
WeakMap and WeakSet hold objects without preventing them from being garbage-collected. They are used for advanced cases such as attaching private data or caches to objects you do not own, so that the data disappears automatically when the object does. They cannot be iterated or counted.
Practice#
Practice exercise
Given const emails = ["a@x.com", "b@x.com", "A@x.com", "c@x.com", "b@x.com"], print the number of unique emails, ignoring case. Then use a Map to count how many emails each domain has in ["a@x.com", "b@y.com", "c@x.com"].
Show solution
const emails = ["a@x.com", "b@x.com", "A@x.com", "c@x.com", "b@x.com"];
const unique = new Set(emails.map((e) => e.toLowerCase()));
console.log(unique.size);
const domains = new Map();
for (const email of ["a@x.com", "b@y.com", "c@x.com"]) {
const domain = email.split("@")[1];
domains.set(domain, (domains.get(domain) ?? 0) + 1);
}
console.log(domains);3
Map(2) { 'x.com' => 2, 'y.com' => 1 }Key takeaway#
Finished this lesson?