JavaScript Set

Why should you care about JavaScript Set?

Set is one of the easiest ways to clean duplicate data. If you work with tags, IDs, filters, or user inputs, Set helps you keep values unique with less code.

A Set works like a guest list where each name can appear only once. It stores unique values, so if you add a duplicate, JavaScript ignores it automatically.

You can store almost any type of value in a Set: numbers, strings, objects, and more. Whenever you need a collection without duplicates, Set is usually the cleanest option.

JavaScript Set - unique values, Set methods (add, has, delete, size, clear), Set vs Array comparison, and iteration

javascript

const mySet = new Set([1, 2, 3, 2, 1]);

console.log(mySet); // Set(3) { 1, 2, 3 }
// Duplicates are automatically removed

Create a Set with new Set(). You can start from an array, or create an empty Set and add values as your program runs.

javascript

// Empty Set
const emptySet = new Set();
emptySet.add(10);
emptySet.add(20);
console.log(emptySet); // Set(2) { 10, 20 }

// Set from an array
const numSet = new Set([1, 2, 3]);
console.log(numSet); // Set(3) { 1, 2, 3 }

// Duplicate values are ignored
const colors = new Set(["red", "blue", "red", "green"]);
console.log(colors); // Set(3) { 'red', 'blue', 'green' }

Sets keep values in the order you add them. When you iterate, values come out in that same sequence. This behavior is called insertion order.

Unlike plain objects (where property order can sometimes be unpredictable), a Set always keeps your values in the exact order you added them.

javascript

const mySet = new Set();
mySet.add("read");
mySet.add("write");
mySet.add("delete");

// Values come out in insertion order
for (const perm of mySet) {
  console.log(perm);
}
// read
// write
// delete

Sets come with a handful of handy methods (plus one property). Here's a quick overview:

  • size - returns the number of elements (property, not a method).
  • add(value) - adds a new value to the Set.
  • has(value) - returns true if the value exists.
  • delete(value) - removes a specific value.
  • clear() - removes all values from the Set.
  • forEach(callback) - iterates over each value.
  • values() - returns an iterator of all values.

Let's go through each one with examples.

size tells you how many values are in your Set. It's a property, not a method, so you write mySet.size without parentheses.

This is similar to array.length in arrays. The count updates automatically when you add or remove values.

javascript

const mySet = new Set([10, 20, 30, 20]);

console.log(mySet.size); // 3 (not 4, because 20 is a duplicate)

mySet.add(40);
console.log(mySet.size); // 4

mySet.delete(10);
console.log(mySet.size); // 3

Want to know if a value is in your Set? That's what has() is for. It returns true if the value exists and false if it doesn't.

Bonus: has() on a Set is faster than indexOf() or includes() on a large array, because Sets are optimized for quick lookups behind the scenes.

javascript

const permissions = new Set(["read", "write", "delete"]);

console.log(permissions.has("write")); // true
console.log(permissions.has("admin")); // false

Use delete() to remove a value from your Set. It returns true if the value was found and removed, or false if it wasn't there.

javascript

const nums = new Set([1, 2, 3, 4]);

console.log(nums.delete(3)); // true  - 3 was removed
console.log(nums.delete(9)); // false - 9 was not in the Set

console.log(nums); // Set(3) { 1, 2, 4 }

Two more commonly used Set methods are add() and clear().

add(value) puts a new value into your Set. If the value already exists, nothing happens (no error). clear() wipes everything out and leaves the Set empty.

javascript

const mySet = new Set();

// add()
mySet.add("a");
mySet.add("b");
mySet.add("a"); // duplicate, ignored
console.log(mySet); // Set(2) { 'a', 'b' }

// clear()
mySet.clear();
console.log(mySet);      // Set(0) {}
console.log(mySet.size); // 0

The add() method returns the Set itself, so you can chain multiple add() calls together: mySet.add(1).add(2).add(3).

Sets do not support indexes. Unlike arrays, you cannot access a Set element by its position using bracket notation like mySet[0].

That's on purpose. Sets are built for answering "is this value in here?" not "what's at position 3?" If you need index access, convert the Set to an array first.

javascript

const mySet = new Set([10, 20, 30]);

// This does NOT work - Sets have no index
console.log(mySet[0]); // undefined

// Convert to array first if you need index access
const arr = [...mySet];
console.log(arr[0]); // 10
console.log(arr[1]); // 20

The easiest way to loop through a Set is with a for...of loop. You'll get each value in the order it was added.

javascript

const languages = new Set(["JavaScript", "Python", "Java"]);

for (const lang of languages) {
  console.log(lang);
}
// JavaScript
// Python
// Java

You can also use set.values() to get an iterator and loop over that instead. Either way, you get the same result.

javascript

const nums = new Set([5, 10, 15]);

for (const val of nums.values()) {
  console.log(val);
}
// 5
// 10
// 15

You can turn a Set into a regular array in two ways: the spread operator ([...set]) or Array.from(). Both do the same thing.

Why convert? Because Sets don't have map(), filter(), or reduce(). Turn it into an array and you get all those methods back.

javascript

const mySet = new Set([1, 2, 3, 4]);

// Using spread operator
const arr1 = [...mySet];
console.log(arr1); // [1, 2, 3, 4]

// Using Array.from()
const arr2 = Array.from(mySet);
console.log(arr2); // [1, 2, 3, 4]

// Practical use - remove duplicates from an array
const withDups = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(withDups)];
console.log(unique); // [1, 2, 3, 4]

forEach() lets you run a function on every value in the Set, one at a time, in the order they were added.

Fun quirk: the callback gets the same value as both its first and second argument. This matches how Map.forEach() works. The third argument is the Set itself.

javascript

const colors = new Set(["red", "green", "blue"]);

colors.forEach(function(value) {
  console.log(value);
});
// red
// green
// blue

// Using arrow function
colors.forEach(color => console.log(color.toUpperCase()));
// RED
// GREEN
// BLUE

A WeakSet is like a Set with two restrictions: it can only store objects (no strings or numbers), and it holds weak references to them.

What does "weak" mean here? It's like a sticky note on an object. If the object gets thrown away (no other variable points to it), the sticky note disappears too. You also can't loop over a WeakSet, and it has no size property.

javascript

const ws = new WeakSet();

let obj1 = { role: "editor" };
let obj2 = { role: "viewer" };

ws.add(obj1);
ws.add(obj2);

console.log(ws.has(obj1)); // true

obj1 = null; // obj1 can now be garbage collected

// WeakSet only supports: add(), has(), delete()
// ws.size and for...of are NOT available

WeakSets are handy when you want to "tag" objects (like DOM elements) without keeping them alive in memory after they're no longer used.

Let's wrap up everything we covered:

  • A Set stores unique values - no duplicates allowed.
  • Sets maintain insertion order.
  • size is a property that returns the count of elements.
  • add(), has(), delete(), and clear() are the core methods.
  • Use for...of or forEach() to iterate over values.
  • Convert a Set to an array with [...set] or Array.from(set).
  • Sets do not support index-based access.
  • A WeakSet holds weak references to objects and is not iterable.

What's next? Now that you understand Sets, let's move on to key-value collections with the next tutorial.

Videos for this topic will be added soon.