Sets and membership: in or not in
A set stores one fact per value: in, or not in. No order, no duplicates, no counts — which is why new Set([1, 2, 2, 3]) has size 3 and deduplication is set semantics. Covers element vs subset, the empty set, infinite sets as rules, and types as sets of values.
The analytics dashboard said 9,412 users clicked the new banner. Marketing was thrilled — until someone opened the export and saw the same user id over and over: every page refresh had appended another click event to an array. The honest number, after deduplication, was 3,107. The fix was one line — new Set(userIds).size — and it is worth slowing down on why that line is the fix. An array answers many questions about its contents: what came first, what came last, how many times does this value appear. A set answers exactly one: is this value in, or not. Dropping order and counts is not a limitation of sets — it is their entire job description, and it is what makes a set the right tool every time the only question that matters is “have I seen this before?”.
After this lesson you can define a set by listing or by rule, write and read ∈ and ∉, explain why order and duplicates do not exist inside a set, distinguish element membership (∈) from subset (⊆), describe the empty set ∅, and recognize types as sets of values.
A set is a collection about which exactly one fact exists per value: membership. A value is either a member (also called an element) of the set, or it is not. The membership symbol is ∈: x ∈ A reads “x is a member of A”, and x ∉ A reads “x is not a member”. The simplest notation lists members between braces: {1, 2, 3} is the set whose members are exactly 1, 2 and 3.
Because membership is the only fact a set stores, order, duplicates, and counts simply do not exist inside one. {1, 2, 3} and {3, 1, 2} are the same set — they answer “yes” to exactly the same membership questions. {1, 1, 2, 3} is also the same set: writing a member twice adds no information, because “in” has no volume knob. Two sets are equal when they have the same members and nothing else.
const clicks = [42, 7, 42, 42, 7];
const unique = new Set(clicks);
unique.size; // 2 — the members are 42 and 7, nothing else
unique.has(42); // true — 42 ∈ unique
unique.has(99); // false — 99 ∉ unique
unique.add(7); // adding an existing member changes nothing
unique.size; // still 2
new Set([1, 2, 2, 3]).size; // 3 — dedup IS set semanticsA set can also be described by a rule (set-builder notation). The notation {x : x is even} reads “the set of all x such that x is even”. Everything after the colon is a predicate — a condition that is true or false for each candidate value. This unlocks infinite sets: the natural numbers ℕ — 0, 1, 2, 3, … — cannot be listed, but every membership question has a definite yes-or-no answer. That is all a set needs.
const isEven = (n) => n % 2 === 0; // the set {x : x is even}, as a rule
isEven(10); // true → 10 ∈ the set
isEven(7); // false → 7 ∉ the set
[1, 2, 3, 4, 5, 6].filter(isEven); // [2, 4, 6]Membership (∈) and subset (⊆) are different claims at different levels. Membership x ∈ A asks about one value: is x on A’s roster? Subset A ⊆ B asks about two sets: is every member of A also in B? Take A = {1, 2}: the value 1 ∈ A is true; the set {1} ⊆ A is true; but {1} ∈ A is false — A’s members are the numbers 1 and 2, not the set {1}. The empty set ∅ (no members) is a subset of every set, but an element of almost none.
Let A = {1, 2, 3}. Classify each claim as true or false, and explain why.
2 ∈ A— True. The number 2 is on A’s roster.{2} ∈ A— False. A’s members are numbers. The set {2} is never listed as a member.{2} ⊆ A— True. {2} has one member, the number 2, which is in A.∅ ⊆ A— True. There is no member of ∅ that could be missing from A — vacuously, the subset condition holds.∅ ∈ A— False. The empty set was never placed on A’s roster of {1, 2, 3}.{∅}has size 1. It is a box containing one thing — an empty box. Not empty.
▸Why this works
Why use a structure that forgets so much? Because forgetting makes answers canonical. There is exactly one set with members 7 and 42 — so “have I seen this value?” has exactly one honest answer, no matter how the data arrived. Most collection bugs come from asking a log a roster question (counting clicks instead of users) or a roster a log question (expecting a set to remember who came first). Choosing the structure is choosing which question your code can ask.
Is 3 ∈ {1, 2, 3}? Answer yes or no.
Are {1, 2, 3} and {3, 1, 2} the same set? Answer yes or no.
Is {1} ∈ {1, 2}? Answer yes or no.
Is {1} ⊆ {1, 2}? Answer yes or no.
What is new Set([5, 3, 5, 3, 5]).size? Type the number.
Let A = {1, 2, 3}. Which pair of claims is BOTH true?
A set is the structure that knows one thing per value: in, or not in. Membership is written x ∈ A; a set can be given by listing — {1, 2, 3} — or by a rule, like {x : x is even}, where the rule is a predicate. Because membership is the only stored fact, sets have no order, no duplicates and no counts: {3, 1, 2} and {1, 1, 2, 3} are the same set as {1, 2, 3}, and new Set([1, 2, 2, 3]) having size 3 is that definition running in your runtime. The two claims to keep apart live at different levels: x ∈ A asks about one value, A ⊆ B asks whether every member of A is in B. The singleton {1} is a subset of {1, 2} but not an element of it; ∅ is a subset of everything, an element of almost nothing, and {∅} is a box holding an empty box — size 1. Types preview the payoff: boolean is the set of true and false, and assignability is the subset question.
Practice
Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.
Something unclear?
Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.