Sets
Intermediate · 16 min read · ▶ live playground · ✦ checkpoint
Some collections are not about order, labels, or lookup keys. They are about one question: "Have I seen this value already?" A Set stores unique values, so duplicates collapse by design instead of becoming cleanup work later.
Set stores unique values
A Set is a collection where each value can appear at most once. Add the same value again, and the Set stays the same size:
const skills = new Set(["JavaScript", "CSS", "JavaScript"]);
console.log(skills.size);
console.log(Array.from(skills).join(", "));
skills.add("HTML");
skills.add("CSS");
console.log(skills.has("CSS"));
console.log(skills.size);
console.log(Array.from(skills).join(", "));→ 2, then JavaScript, CSS. After adding values, CSS is present, the size is 3, and the values are JavaScript, CSS, HTML.
Think of a Set as a guest-list stamp at a door. The first time a name arrives, it gets stamped in. If the same name comes back, the list does not grow; the answer is still "already here."
Sets remember the order values were first added. That is why JavaScript stays before CSS, and adding CSS again does not move it to the end.
Add, check, delete
The everyday Set tools match the questions Sets are built to answer:
add(value)puts a value in the Set.has(value)asks whether the value is already there.delete(value)removes a value and returnstrueif something was removed.sizetells you how many unique values are present.
const completed = new Set();
completed.add("variables");
completed.add("arrays");
completed.add("objects");
completed.add("arrays");
console.log(completed.size);
console.log(completed.has("objects"));
console.log(completed.has("maps"));
console.log(completed.delete("variables"));
console.log(completed.delete("functions"));
console.log(Array.from(completed).join(", "));→ 3, true, false, true, false, then arrays, objects.
The duplicate "arrays" did not create a second entry. delete("functions") returned false because that value was not in the Set.
For primitive values like strings and numbers, uniqueness feels natural. For objects, Section 7's identity rule still applies:
const firstMina = { name: "Mina" };
const secondMina = { name: "Mina" };
const reviewers = new Set([firstMina, secondMina, firstMina]);
console.log(reviewers.size);
console.log(reviewers.has(firstMina));
console.log(reviewers.has({ name: "Mina" }));→ 2, then true, then false.
Two object literals with the same shape are still two different objects. The Set stores reference tickets, not a deep comparison of the object bodies.
Dedupe an array in one line
To dedupe means to remove duplicate values. The most common Set move is turning an array into a Set, then spreading it back into an array:
const names = ["Mina", "Rae", "Mina", "Sol", "Rae"];
const uniqueNames = [...new Set(names)];
console.log(uniqueNames.join(", "));
console.log(names.length);
console.log(uniqueNames.length);→ Mina, Rae, Sol, then 5, then 3.
Read new Set(names) as "keep the first copy of each value." Read [...new Set(names)] as "turn those unique values back into an array." The original array does not change.
This is perfect for tags, usernames, IDs, and other lists where repeated primitive values should collapse. If your array contains objects, remember the identity rule from the previous section: two separate { name: "Mina" } objects are still two separate values.
Try it — track unique badges
Run this, then inspect earnedBadges at the › prompt. Try earnedBadges.has("arrays"), earnedBadges.size, and [...earnedBadges].
Notice the two shapes working together. The Set is the truth for membership: one badge exists or it does not. The array is useful when you want display tools like toSorted() and join().
Membership testing at speed
Arrays can answer "is this value present?" with includes, and you already know that tool. But when membership is the main job, a Set says that job out loud with has.
const blockedUsernames = new Set(["bot-7", "spam-box", "fake-admin"]);
const signups = ["mina", "bot-7", "rae", "fake-admin", "sol"];
const allowed = signups.filter(username => {
return !blockedUsernames.has(username);
});
console.log(allowed.join(", "));
console.log(blockedUsernames.has("spam-box"));
console.log(blockedUsernames.has("mina"));→ mina, rae, sol, then true, then false.
This is the membership pattern: keep the "known values" in a Set, then ask has while processing another list. It reads cleanly, and it stays comfortable when the blocked list grows. You do not need to write a loop that scans the blocked usernames by hand.
Set algebra
Set algebra means combining whole Sets to answer group questions. Modern JavaScript gives Sets methods with the same names you would use on a whiteboard:
a.union(b)means values inaorb.a.intersection(b)means values in bothaandb.a.difference(b)means values inabut not inb.
const frontend = new Set(["Mina", "Rae", "Sol"]);
const backend = new Set(["Rae", "Kai", "Sol"]);
const everyone = frontend.union(backend);
const bothTeams = frontend.intersection(backend);
const frontendOnly = frontend.difference(backend);
const backendOnly = backend.difference(frontend);
console.log(Array.from(everyone).join(", "));
console.log(Array.from(bothTeams).join(", "));
console.log(Array.from(frontendOnly).join(", "));
console.log(Array.from(backendOnly).join(", "));
console.log(frontend.size);→ Mina, Rae, Sol, Kai, then Rae, Sol, then Mina, then Kai, then 3.
These methods create new Sets. frontend still has size 3 after the algebra runs.
The receiver matters for difference. frontend.difference(backend) asks "what is in frontend but not backend?" backend.difference(frontend) asks the opposite question. union and intersection feel symmetrical, but difference has a left side and a right side.
Set algebra shines when your data is already about membership: students enrolled in two workshops, features enabled in two plans, tags shared between articles, users who completed one step but not another. You could build those answers with filter and has, but the algebra names the intent directly.
Checkpoint
Answer all three to mark this lesson complete
Sets give you a clean model for unique values and membership questions. Next, you will put Arrays, Objects, Maps, and Sets side by side so the data shape can tell you which structure to choose.