Set in JavaScript is a built in collection type used to store unique values. Unlike arrays, which allow duplicate entries and rely heavily on numeric indexes, a set is focused on membership. Its main idea is simple: a value either exists in the set or it does not. That makes `Set` especially useful when you want to remove duplicates, track seen items, or quickly check whether a value has already been added.
Many developers first meet `Set` when they need to remove duplicate values from an array. That is a common and practical use case, but it is not the only one. A set can also represent selected tags, visited routes, processed IDs, unique permissions, or any collection where uniqueness matters more than order based indexing. Understanding `Set` helps you model these problems more cleanly instead of forcing arrays to do a job they are not designed to do well.
Why Set exists
Arrays are excellent when you need ordered lists, repeated traversal, and index based access. But arrays do not naturally enforce uniqueness. If you want to make sure a value appears only once, you usually need extra logic such as `includes` checks or filtering. `Set` exists because uniqueness is such a common requirement that JavaScript benefits from a dedicated collection built around that idea.
This is not only about convenience. It is also about expressing intent. When another developer sees an array, they assume it is a general list. When they see a set, they immediately know uniqueness is part of the design. Good code benefits from data structures that make the intent visible rather than hiding it behind manual rules.
| Structure | Main strength | Typical use |
|---|---|---|
| Array | Ordered list with indexes | Rendering lists, sequential processing |
| Object | Named structured data | Records, configuration, entities |
| Map | Dynamic key value collection | Registries, caches, lookups |
| Set | Unique value collection | Deduplication, membership tracking |
Creating a Set
You create a set with the `Set` constructor. It can start empty, or it can be initialized from an iterable such as an array. If the source contains duplicates, the set automatically keeps only one copy of each unique value. This behavior is one of the most attractive parts of the type because it removes the need for extra deduplication logic in many cases.
const skills = new Set();
skills.add("HTML");
skills.add("CSS");
skills.add("CSS");
skills.add("JavaScript");
console.log(skills);
const uniqueNumbers = new Set([1, 2, 2, 3, 4, 4]);
console.log(uniqueNumbers);
In both cases, duplicate values do not accumulate. The set stores only one instance of each value. This gives it a very different personality from an array, where duplicates are perfectly normal unless you block them manually.
Basic Set operations
The core methods are `add`, `has`, `delete`, and `clear`. Together they cover insertion, membership checking, removal of one value, and removal of everything. Sets also expose a `size` property so you can immediately see how many unique entries are stored.
const topics = new Set();
topics.add("DOM");
topics.add("Events");
console.log(topics.has("DOM"));
console.log(topics.size);
topics.delete("Events");
console.log(topics.has("Events"));
topics.clear();
console.log(topics.size);
These operations make sets very comfortable for membership based logic. Instead of asking where a value is located in an array, the code can ask the more important question directly: is the value present or not.
Set and uniqueness
The strongest mental model for `Set` is that it is not really about positions. It is about presence. If the same primitive value is added again, the set remains unchanged because that value is already part of the collection. This makes it ideal for tag systems, access flags, processed identifiers, and any other place where duplicates would be redundant or misleading.
That is also why a set often simplifies business logic. Instead of maintaining a list and constantly checking whether a value is already present before adding it, you can let the set enforce the uniqueness rule for you. The code becomes both shorter and more honest about its real purpose.
Converting between arrays and sets
One of the most practical patterns is moving between arrays and sets. An array may be the natural input format because it comes from a form, an API, or the UI. A set may then be used to remove duplicates or perform membership checks. After that, the result can be turned back into an array if the rest of the program expects array methods or rendering behavior.
const tags = ["js", "web", "js", "dom", "web"];
const uniqueTags = [...new Set(tags)];
console.log(uniqueTags);
This is one of the most famous one line JavaScript patterns. It works because `Set` removes duplicates and the spread syntax converts the set back into an array. The pattern is concise, but it is also conceptually clean: array in, unique values enforced, array out.
Iterating over a Set
Sets are iterable, which means they work naturally with `for…of`. You can also use methods like `forEach`. Iteration order follows insertion order, so the values come out in the order they were first added. That makes sets convenient in workflows where both uniqueness and stable entry order matter.
const tools = new Set(["HTML", "CSS", "JavaScript"]);
for (const tool of tools) {
console.log(tool);
}
tools.forEach(tool => console.log(tool));
The iteration style is simple because sets store values directly. There is no separate key value pair the way there is in a map. The collection is all about the unique values themselves.
Objects inside a Set
Sets work with objects too, but object uniqueness is based on reference identity, not on matching shape. Two different object literals with the same visible properties are still different references, so a set treats them as different values. This detail matters because developers sometimes expect object values with the same content to collapse into one entry automatically, which does not happen by default.
const a = { id: 1 };
const b = { id: 1 };
const records = new Set();
records.add(a);
records.add(b);
console.log(records.size);
This size becomes `2` because `a` and `b` are different object references. The uniqueness rule still exists, but it is based on identity, not structural equality. This is important in caching, selection tracking, and object based workflows.
Set versus Array in practical code
If the code needs duplicates, random index access, or many list transformation methods, an array is still the better default. If the code needs uniqueness and fast membership style thinking, a set is often the better fit. The right choice depends on the shape of the problem, not on which syntax looks more modern.
For example, a shopping cart line list is usually an array because order and repeated entries may matter. A selected category list where each category should appear only once is a strong candidate for a set. Choosing based on the real data behavior makes later code simpler and avoids unnecessary checking logic.
Common use cases for Set
- Removing duplicate values from arrays.
- Tracking processed IDs or visited pages.
- Managing selected tags, filters, or permissions where each value should appear once.
- Checking membership without maintaining manual duplicate prevention logic.
- Representing unique runtime references such as active objects or subscribers.
Best practices for Set
Use a set when uniqueness is part of the design, not as a fashionable replacement for arrays. Keep in mind that sets are collections of values, not of named fields. Also remember that object values are compared by reference, not by deep content. These rules make sets predictable once the underlying model is understood.
Set is one of those JavaScript features that becomes more useful the more your code deals with real data constraints. Once you see membership and uniqueness as first class requirements instead of as extra cleanup steps, `Set` starts to feel like a natural and practical tool rather than a niche collection type.
FAQ
What is Set in JavaScript?
Set is a built in collection type that stores unique values and prevents duplicate entries of the same value.
When should Set be used instead of an array?
Use Set when uniqueness and membership checks are more important than duplicates, indexing, or array style list behavior.
Can Set remove duplicate values from an array?
Yes. A common pattern is to pass the array into a set and then spread the set back into a new array of unique values.
Set and data quality
One of the most practical reasons to use a set is data quality. Duplicate values are often not just annoying. They can change counts, distort summaries, create repeated UI entries, or trigger repeated processing work. A set prevents that class of problem by making uniqueness part of the collection itself rather than leaving it as a rule developers must remember to enforce manually every time new data arrives.
This makes sets especially helpful when data comes from uncertain sources such as user input, merged arrays, or external systems. Instead of cleaning duplicates later in several different places, the program can centralize that rule in the data structure. The collection itself becomes honest about what it is allowed to contain, which usually leads to simpler and more maintainable logic.
Thinking in membership instead of position
Another good mental shift is to stop thinking about a set as a list with fewer features. A set is not really about positions at all. It is about whether a value belongs to a collection. When the real question in your code is “has this already been seen” or “is this selected,” a set often matches that question more naturally than an array ever will.
That is why sets tend to feel better over time in permission systems, deduplication logic, and selection state. The code moves closer to the actual business rule and farther away from mechanical array management. In practice, that usually means fewer checks, fewer accidental duplicates, and cleaner intent.