Academic Block

JavaScript Sets and Maps Get Certified

Set and Map are built-in collection types that solve common problems more cleanly than plain arrays and objects. A Set stores unique values. A Map stores key-value pairs where keys can be of any type.

In this lesson you will learn how to create and use both, how they differ from arrays and objects, and when each is the right tool.

Creating a Set

A Set is created with new Set(). You can pass an iterable (such as an array) to seed it with values. Duplicates are automatically ignored.

What this code does: Creating a Set from an array automatically removes duplicates. The size reflects only the unique values.

const tags = new Set(["js", "css", "js", "html"]);
console.log(tags);
console.log(tags.size);

Common Set Methods

add() inserts a value, has() checks for existence, delete() removes a value, and clear() empties the entire set.

What this code does: Use add, has, and delete to manage membership. Adding an existing value has no effect.

const colors = new Set();
colors.add("red");
colors.add("blue");
colors.add("red"); // ignored
console.log(colors.has("blue"));
colors.delete("red");
console.log(colors);

Iterating Over a Set

Sets are iterable. You can loop with for...of or use forEach. Insertion order is preserved.

What this code does: Looping a Set with for...of visits each unique value in the order it was added.

const cities = new Set(["Lisbon", "Porto", "Braga"]);
for (const city of cities) {
    console.log(city);
}

Converting Between Set and Array

Use the spread operator or Array.from() to turn a Set into an array (and vice versa).

What this code does: Spread converts a Set into an array so you can use array methods. The result is a regular array of the unique values.

const unique = new Set([1, 2, 2, 3]);
const asArray = [...unique];
console.log(asArray);

What this code does: A common pattern for removing duplicates: wrap the array in a Set, then spread back into an array. Only unique ratings remain.

const submittedRatings = [5, 3, 5, 4, 3, 5, 2];
const uniqueRatings = [...new Set(submittedRatings)];
console.log(uniqueRatings);

Creating a Map

A Map is created with new Map(), optionally passing an array of [key, value] pairs.

What this code does: A Map stores key-value pairs. You can create one from an array of pairs. Keys can be any type, not just strings.

const inventoryLevels = new Map([
    ["widgets", 120],
    ["gadgets", 45]
]);
console.log(inventoryLevels);

Common Map Methods

set() adds or updates a key-value pair, get() retrieves a value, has() checks for a key, and delete() removes a key-value pair.

What this code does: Use set, get, has, and delete to manage entries. Missing keys return undefined from get.

const inventoryLevels = new Map();
inventoryLevels.set("widgets", 120);
inventoryLevels.set("gadgets", 45);
console.log(inventoryLevels.get("widgets"));
console.log(inventoryLevels.has("sprockets"));
inventoryLevels.delete("gadgets");
console.log(inventoryLevels);

Map Keys Can Be Any Type

Unlike a plain object, whose keys are always converted to strings, a Map can use objects, functions, or any other value as a key without converting it.

What this code does: Map keys can be objects, not only strings. Each user object is used as a key so login times are stored per user instance.

const userAlice = { name: "Alice" };
const userBen = { name: "Ben" };
const lastLogin = new Map();
lastLogin.set(userAlice, "2026-09-01");
lastLogin.set(userBen, "2026-09-05");
console.log(lastLogin.get(userAlice));

Iterating Over a Map

A Map can be looped over directly with for...of, and each iteration gives you a [key, value] pair, which pairs naturally with array destructuring.

What this code does: Looping a Map with for...of yields [key, value] pairs. Each item and its quantity are printed in insertion order.

const inventoryLevels = new Map([
    ["widgets", 120],
    ["gadgets", 45],
    ["sprockets", 8]
]);
for (const [item, quantity] of inventoryLevels) {
    console.log(item + ": " + quantity);
}

You can also access just the keys, values, or entries with keys(), values(), and entries(), similar to Object.keys() and friends.

Map vs. Object

Aspect Object Map
Key types Strings and symbols only Any value, including objects and functions
Key order Mostly insertion order, with some exceptions Always insertion order
Size Object.keys(obj).length map.size (a direct property)
Iteration Requires Object.entries() or similar Directly iterable with for…of

Set vs. Array

Aspect Array Set
Duplicate values Allowed Automatically ignored
Access by index Yes (arr[0]) No direct index access
Checking existence includes() (scans the array) has() (generally faster for large collections)

A Brief Note on WeakMap and WeakSet

JavaScript also provides WeakMap and WeakSet, which behave similarly to Map and Set, but only allow objects as keys (or values, for WeakSet) and don’t prevent those objects from being garbage collected when nothing else references them.

What this code does: A WeakMap holds object keys without preventing garbage collection. Metadata is attached to the session object and can be looked up while the session exists.

let session = { userId: 42 };
const sessionMetadata = new WeakMap();
sessionMetadata.set(session, { loginTime: Date.now() });
console.log(sessionMetadata.has(session));

Because WeakMap and WeakSet aren’t directly iterable and don’t have a size property, they’re mainly used for specialized memory-management scenarios rather than everyday data storage.

Practical Example

Let’s use a Set and a Map together to track unique visitors and count how many times each one visited.

What this code does: Combine Set and Map: unique visitor count from a Set, and per-visitor visit counts from a Map built by iterating the same list.

const pageViews = ["userA", "userB", "userA", "userC", "userB", "userA"];
const uniqueVisitors = new Set(pageViews);
console.log("Unique visitors:", uniqueVisitors.size);

const visitCounts = new Map();
for (const visitor of pageViews) {
    visitCounts.set(visitor, (visitCounts.get(visitor) || 0) + 1);
}
for (const [visitor, count] of visitCounts) {
    console.log(visitor + " visited " + count + " time(s).");
}

Common Mistakes With Sets and Maps

  • Trying to access a Set element by index, like an array, when Set doesn’t support index-based access.
  • Calling .size as a function (.size()), when it’s actually a property, not a method.
  • Forgetting that object keys in a plain object are always converted to strings, unlike Map keys.
  • Assuming a Set automatically sorts its values — it only preserves insertion order, not numeric or alphabetical order.
  • Using a Map or Set when a simple array or object would be just as clear, adding unnecessary complexity for straightforward cases.

Best Practices for Sets and Maps

  • Use a Set when you need to guarantee uniqueness or frequently check whether a value already exists.
  • Use a Map when your keys aren’t simple strings, or when key order and frequent additions/removals matter.
  • Use the spread operator to convert between Set and array when you need array-specific methods like map() or filter().
  • Stick with plain objects for simple, string-keyed data that doesn’t need Map‘s extra capabilities.
  • Reserve WeakMap and WeakSet for specialized cases involving memory management, rather than everyday data storage.

Quick Summary

  • A Set stores a collection of unique values, with no duplicates allowed.
  • A Map stores key-value pairs where keys can be any type, not just strings.
  • Both are directly iterable with for...of and preserve insertion order.
  • Set is commonly used to remove duplicates from an array using the spread operator.
  • Map offers a size property and more predictable iteration compared to a plain object.
  • WeakMap and WeakSet are specialized variants used mainly for memory-sensitive scenarios.

Try It Yourself

Modify the code below. Try adding a duplicate skill to see it get ignored, or adding a new key-value pair to the map.

What this code does: Practice example: a Set ignores the duplicate skill, and a Map stores skill levels. Try adding another skill or level, then click Test My Code.

const skills = new Set(["JavaScript", "CSS", "JavaScript", "HTML"]);
console.log(skills);
console.log(skills.size);

const skillLevels = new Map([
    ["JavaScript", "Advanced"],
    ["CSS", "Intermediate"]
]);
console.log(skillLevels.get("CSS"));
Tip: If you catch yourself writing if (!array.includes(value)) array.push(value) to avoid duplicates, that’s usually a sign a Set would express the same intent more directly.

Understanding Set and Map is useful before moving on to iterators, generators, and more advanced JavaScript concepts.

🧪 Test Your JavaScript Code

Edit the code on the left and click “Run Code” to see the console output on the right.

📝 JavaScript Code
👁 Console Output

Click “Run Code” to see the output here.

Ctrl + Enter to run code Esc to close