Set в JavaScript: что это и как работать с множествами
Храним уникальные значения, удаляем повторы и сравниваем списки.
Set в JavaScript помогает работать со списками, в которых каждое значение должно встречаться один раз. С его помощью можно собрать теги из нескольких источников, убрать повторяющиеся адреса или проверить, какие товары из корзины есть в наличии.
В статье разберём, как создавать множества Set, добавлять и удалять элементы, сравнивать списки и выбирать между Set и массивом.
Содержание
- Что такое множество Set в JavaScript и как его создать
- Методы и свойства Set
- Перебор элементов в Set
- Особенности работы Set в JavaScript
- Преобразования Set
- Типичные ошибки при работе с Set
- Практика
- Главное о структуре данных Set в JavaScript
Что такое множество Set в JavaScript и как его создать
Set — это коллекция, то есть набор значений, с которым программа работает как с единым целым. Каждое значение хранится в Set один раз. Например, если передать ему теги 'js', 'html', 'js', останутся два: 'js' и 'html'.
Посмотрим, как создать такое множество. В примерах ниже console.log() выводит результат в консоль.
Создадим множество:
// Создаём пустое множество и сохраняем его под именем tags
const tags = new Set();
// Выводим множество в консоль
console.log(tags); // Set(0) {}Переменная хранит значение под именем, по которому к нему можно обратиться дальше в коде. Здесь имя переменной — tags. Слово const создаёт переменную, знак = сохраняет в ней значение справа, а new Set() создаёт новое множество. Скобки пустые: множество создаётся без начальных элементов.
Добавим теги:
// Создаём множество для тегов
const tags = new Set();
// Добавляем три значения, одно из которых повторяется
tags.add('js');
tags.add('html');
tags.add('js');
// Повторный тег занимает одно место
console.log(tags); // Set(2) {'js', 'html'}add() — метод множества, то есть действие, которое можно с этим множеством выполнить. Запись tags.add ('js') означает: «Добавь значение 'js' во множество tags». Точка связывает метод с коллекцией, а в скобках мы указываем значение, которое нужно добавить.
Мы трижды выполнили add() и получили два элемента. Set сохранило порядок первого добавления: сначала 'js', затем 'html'.
Можно сразу создать Set из массива. Массив — это список значений, к которым можно обращаться по номеру. В коде его записывают в квадратных скобках, а значения разделяют запятыми.
// Создаём массив, в котором тег js повторяется
const sourceTags = ['js', 'html', 'js'];
// Передаём массив при создании множества
const tags = new Set(sourceTags);
// В Set два элемента, исходный массив по-прежнему содержит три
console.log(tags.size); // 2
console.log(sourceTags.length); // 3size показывает, сколько элементов в Set, а length — сколько элементов в массиве. Сам массив sourceTags остался прежним: на его основе мы создали отдельную коллекцию.

Читайте также:
Методы и свойства Set в JavaScript
С помощью add() мы уже добавили значение во множество. Теперь разберём другие основные действия: проверим, есть ли там нужный элемент, удалим элемент и очистим множество целиком.
Метод has() проверяет, есть ли значение во множестве. Результат проверки — логическое значение: true означает «да», false — «нет». По этому ответу программа выбирает, что делать дальше.
// Создаём множество из двух тегов
const tags = new Set(['js', 'html']);
// Проверяем наличие каждого тега
console.log(tags.has('js')); // true — тег есть
console.log(tags.has('css')); // false — такого тега пока нет
// Удаляем существующий тег
console.log(tags.delete('html')); // true — удаление выполнено
// Пробуем удалить тот же тег ещё раз
console.log(tags.delete('html')); // false — удалять уже нечего
// Проверяем число оставшихся элементов
console.log(tags.size); // 1
// Удаляем все элементы
tags.clear();
console.log(tags.size); // 0has() только проверяет наличие элемента, delete() удаляет указанный элемент и сообщает, удалось ли это сделать, clear() удаляет все элементы сразу.
size — это свойство, то есть характеристика коллекции, которая показывает число элементов. Обратите внимание, что мы записываем size без скобок. Скобки после имени метода означают, что мы его вызываем — запускаем указанное действие. Например, tags.clear() очищает множество, а tags.size показывает его текущий размер.
Перебор элементов Set в JavaScript
Допустим, нужно вывести каждый тег отдельно. Перебор означает, что программа по очереди берёт элементы коллекции и выполняет с ними действие.
Для этого подойдёт цикл for…of. Цикл повторяет указанный участок кода.
// Создаём множество из двух тегов
const tags = new Set(['js', 'html']);
// По очереди получаем каждый тег
for (const tag of tags) {
// Выводим текущий тег
console.log(tag);
}
// Результат:
// js
// htmlЗапись const tag of tags означает: «Бери по очереди значения из tags и называй каждое tag». Для каждого значения программа выполняет код, записанный между фигурными скобками.

Читайте также:
Другой способ перебрать элементы — forEach(). Этому методу передают функцию — участок кода, который можно запустить для выполнения действия. В нашем примере функция выводит полученный тег.
// Создаём множество
const tags = new Set(['js', 'html']);
// Для каждого тега вызываем функцию
tags.forEach((tag) => {
// tag получает значение текущего элемента
console.log(tag);
});
// Результат:
// js
// htmlЗапись (tag) => {… } создаёт стрелочную функцию. Её параметр tag — имя для значения, которое функция получает при вызове. По этому имени мы обращаемся к значению внутри функции. forEach() вызывает её для каждого элемента: сначала передаёт 'js', затем 'html'.

Читайте также:
Такая функция может принимать ещё два параметра. Второй повторяет значение элемента, а третий содержит само множество. В нашем примере достаточно первого параметра.
Методы values() и keys() возвращают итератор — объект, который выдаёт элементы по очереди, в Set они работают одинаково. Итератор можно использовать в том же цикле:
// Создаём множество
const tags = new Set(['js', 'html']);
// values() выдаёт значения по очереди
for (const tag of tags.values()) {
console.log(tag); // Сначала js, затем html
}Метод entries() выдаёт для каждого элемента пару одинаковых значений:
// Создаём множество
const tags = new Set(['js', 'html']);
// Получаем пары значений
for (const pair of tags.entries()) {
console.log(pair);
}
// Результат:
// ['js', 'js']
// ['html', 'html']Такой формат помогает работать с Set и Map похожим образом. Map — коллекция пар «ключ — значение»: по ключу можно найти связанное с ним значение. В Set каждую пару составляют две копии значения элемента. Для обычного перебора удобнее начинать с for…of или forEach().
Особенности работы Set в JavaScript
Set может хранить значения разных типов. Тип определяет, что перед нами: число, текст, логическое значение или объект.
Число 1 и строка '1' сохраняются отдельно:
// Передаём число, строку и повторное число
const values = new Set([1, '1', 1]);
// Повторное число занимает одно место, строка — другое
console.log(values.size); // 2NaN — специальное числовое значение, которое появляется, например, при неудачном преобразовании текста в число. Повторные NaN занимают во множестве одно место. Положительный и отрицательный ноли (0 и -0) тоже считаются одинаковыми.
// Проверяем особые числовые значения
const values = new Set([NaN, NaN, 0, -0]);
// Остаются NaN и 0
console.log(values.size); // 2
Читайте также:
Объект — это набор свойств, у каждого из которых есть имя и значение. В Set объекты добавляют методом add() или передают при создании множества — new Set([first, second]).
Если создать две отдельные карточки товара с одинаковым названием 'Монитор', множество сохранит обе: каждый созданный объект для него — отдельное значение.
// Каждая запись в фигурных скобках создаёт отдельный объект
const first = { title: 'Монитор' };
const second = { title: 'Монитор' };
// Передаём два разных объекта с одинаковым содержимым
const products = new Set([first, second]);
console.log(products.size); // 2Переменная first хранит ссылку на первый объект, а second — на второй. Ссылка указывает на конкретный объект и позволяет к нему обратиться. Set сравнивает, на какой объект указывают ссылки.

Читайте также:
Если дважды передать во множество один и тот же объект, в нём останется один элемент:
// Создаём один объект
const product = { title: 'Монитор' };
// Дважды передаём ссылку на него
const products = new Set([product, product]);
console.log(products.size); // 1Поэтому с помощью Set можно убрать повторы среди чисел и строк. Для карточек товаров сначала решим, что считать совпадением: один и тот же объект, одинаковый ID (уникальный номер) товара или совпадающие характеристики.
Преобразования Set в JavaScript
Иногда требуется использовать массив, чтобы, например, получить первый элемент по его номеру. Такой номер называется индексом. В JavaScript отсчёт начинается с нуля.
Метод Array.from() создаёт массив из элементов Set:
// Создаём множество тегов
const tags = new Set(['js', 'html']);
// Собираем его элементы в массив
const array = Array.from(tags);
// Индекс 0 соответствует первому элементу
console.log(array[0]); // js
console.log(array); // ['js', 'html']То же преобразование можно записать как […tags]. Три точки — оператор расширения: здесь он извлекает элементы Set, а квадратные скобки собирают их в массив.
// Создаём множество
const tags = new Set(['js', 'html']);
// Раскрываем его элементы внутри нового массива
const array = [...tags];
console.log(array); // ['js', 'html']Чтобы получить множество из массива, передадим массив в new Set(). Этот приём нам уже знаком:
// Создаём массив с повторами
const array = ['js', 'html', 'js'];
// Создаём множество на его основе
const tags = new Set(array);
console.log(tags.size); // 2В следующих практических примерах будем пользоваться Array.from(): так легче увидеть, на каком шаге мы превращаем множество в массив.
Типичные ошибки при работе с Set в JavaScript
Частая ошибка — ожидать, что Set объединит отдельно созданные объекты с одинаковым содержимым. Выше мы увидели, что каждый такой объект занимает во множестве своё место.
Допустим, в списке дважды встретилась карточка одного товара. У товара есть ID — уникальный номер. Если мы считаем карточки одинаковыми по этому номеру, можно хранить уже встреченные ID в Set.
// Две карточки относятся к одному товару
const products = [
{ id: 101, title: 'Монитор' },
{ id: 101, title: 'Монитор' }
];
// В Set будем хранить номера уже встреченных товаров
const seenIds = new Set();
// В массив будем складывать отобранные карточки
const uniqueProducts = [];
// Проверяем каждую карточку
for (const product of products) {
// Проверяем, встречался ли такой номер
const alreadySeen = seenIds.has(product.id);
// === сравнивает значения; false означает, что номер новый
if (alreadySeen === false) {
// Запоминаем номер товара
seenIds.add(product.id);
// push() добавляет карточку в конец массива
uniqueProducts.push(product);
}
}
// В массиве одна карточка
console.log(uniqueProducts.length); // 1Конструкция if выполняет код в фигурных скобках, если условие в круглых скобках возвращает true. Здесь alreadySeen === false проверяет, впервые ли встретился номер. Когда проверяем первую карточку, номер встречается впервые: сохраняем его и карточку. Когда проверяем вторую, номер уже есть в Set, поэтому пропускаем добавление. Один и тот же ID займёт одно место, даже если другие свойства карточек различаются.
Другая ошибка связана со строками. Для Set адреса различаются, если различаются пробелы по краям или регистр букв (то есть одни буквы большие, а другие — маленькие).
// В строках есть различия в пробелах и регистре
const rawEmails = ['test@domain.com', ' Test@domain.com '];
// Создаём множество без подготовки строк
const emails = new Set(rawEmails);
console.log(emails.size); // 2Для нашей задачи будем считать такие записи одним адресом. Поэтому сначала приведём строки к общему виду, а затем добавим их в Set:
// Исходные записи
const rawEmails = ['test@domain.com', ' Test@domain.com '];
// Здесь соберём подготовленные адреса
const emails = new Set();
// Обрабатываем каждую строку
for (const email of rawEmails) {
// trim() удаляет пробелы по краям строки
const withoutSpaces = email.trim();
// toLowerCase() переводит буквы в нижний регистр
const normalized = withoutSpaces.toLowerCase();
// Добавляем подготовленный адрес
emails.add(normalized);
}
console.log(emails.size); // 1
console.log(Array.from(emails)); // ['test@domain.com']После подготовки обе строки совпадают, поэтому в Set остаётся один адрес. Способ подготовки зависит от задачи: в нашем примере мы договорились игнорировать пробелы по краям и регистр букв.
Практика
Попробуйте самостоятельно решить четыре задачи с помощью Set. Сначала напишите свой вариант, затем сравните его с решением и разбором.
Проверка уникальности
В массиве ids хранятся номера товаров: [101, 102, 103, 102]. С помощью Set проверьте, все ли номера уникальны. Сохраните ответ в isUnique и выведите его в консоль: true, если каждый номер встречается один раз, и false, если есть повторы.
Решение
// В исходном массиве четыре номера
const ids = [101, 102, 103, 102];
// В Set останутся только уникальные номера
const uniqueIds = new Set(ids);
// Сравниваем число элементов
const isUnique = ids.length === uniqueIds.size;
console.log(ids.length); // 4
console.log(uniqueIds.size); // 3
console.log(isUnique); // falseОператор === проверяет, равны ли значения, и учитывает их типы. Здесь мы сравниваем числа 4 и 3. Они различаются, поэтому получаем false. Имя isUnique означает «Все значения уникальны?». Ответ false показывает, что в списке есть повторы.
Пересечение множеств
В корзине лежат товары ['Яблоко', 'Банан', 'Киви'], а в наличии есть ['Банан', 'Киви', 'Манго']. Создайте множества inCart и inStock для этих списков. Найдите их пересечение — товары, которые есть в обоих множествах. Выведите результат в консоль в виде массива.
Решение
// Создаём два множества товаров
const inCart = new Set(['Яблоко', 'Банан', 'Киви']);
const inStock = new Set(['Банан', 'Киви', 'Манго']);
// Здесь соберём общие товары
const intersection = new Set();
// По очереди проверяем товары из корзины
for (const item of inCart) {
// Если товар есть в наличии, добавляем его в результат
if (inStock.has(item)) {
intersection.add(item);
}
}
// Показываем результат в виде массива
console.log(Array.from(intersection)); // ['Банан', 'Киви']Для яблока has() вернёт false, поэтому программа пропустит этот товар. Для банана и киви проверка вернёт true — оба товара попадут в результат.
Объединение множеств
Есть два списка тегов: firstTags = ['js', 'html'] и secondTags = ['html', 'css']. С помощью Set объедините их в один список без повторов. Сохраните порядок первого появления тегов: сначала из первого списка, затем из второго. Выведите результат в консоль в виде массива.
Решение
// Исходные списки тегов
const firstTags = ['js', 'html'];
const secondTags = ['html', 'css'];
// Сначала добавляем теги первого списка
const allTags = new Set(firstTags);
// Затем по очереди добавляем теги второго списка
for (const tag of secondTags) {
allTags.add(tag);
}
// Повторный html остаётся в одном экземпляре
console.log(Array.from(allTags)); // ['js', 'html', 'css']Set сохраняет 'html' в одном экземпляре даже после повторного добавления. Поэтому вызываем add() для каждого тега: коллекция сама проверяет, встречалось ли значение раньше.
Разность множеств
Заказаны товары ['Монитор', 'Клавиатура', 'Мышка'], а доставлены ['Клавиатура', 'Мышка']. Создайте для этих списков множества ordered и delivered. Найдите их разность — то есть товары из заказа, которые ещё предстоит доставить. Выведите результат в консоль в виде массива.
Решение
// Заказанные и доставленные товары
const ordered = new Set(['Монитор', 'Клавиатура', 'Мышка']);
const delivered = new Set(['Клавиатура', 'Мышка']);
// Здесь соберём товары, ожидающие доставки
const pending = new Set();
// Проверяем каждый заказанный товар
for (const item of ordered) {
// Узнаём, доставлен ли товар
const isDelivered = delivered.has(item);
// ! меняет true на false, а false — на true
if (!isDelivered) {
// Сохраняем товар, который ещё предстоит доставить
pending.add(item);
}
}
console.log(Array.from(pending)); // ['Монитор']Для монитора isDelivered равно false. Оператор ! меняет false на true, поэтому программа выполняет код внутри if и добавляет монитор в pending. Для уже доставленных товаров условие равно false, и программа пропускает их.
В современных версиях JavaScript у Set также есть методы intersection(), union() и difference() для этих трёх операций. В примерах мы использовали знакомые add(), has() и цикл, чтобы увидеть каждое действие программы.
Главное о Set в JavaScript
Множество Set хранит уникальные значения и помогает проверять, есть ли среди них нужное. С ним можно собрать список тегов без повторов, запомнить уже встреченные ID или найти общие элементы двух списков.
Массив пригодится, когда нужно сохранять повторы и получать элементы по индексу. Например, в нём можно сохранить каждое добавление товара в корзину, а с помощью Set — получить список разных товаров.
Обе коллекции сохраняют порядок добавления. Чтобы выбрать подходящую, решите, что нужно сохранить: все добавленные значения с повторами или только уникальные элементы.
Сравним основные возможности.
| Характеристика | Set (Множество) | Array (Массив) |
|---|---|---|
| Тип данных | Коллекция уникальных значений | Последовательность любых значений |
| Уникальность элементов | Присутствует | Отсутствует |
| Порядок добавления | Сохраняется | Сохраняется |
| Доступ по индексу | Нет | Есть |
| Добавить элемент | add() | push() |
| Проверить элемент | has() — проверка наличия значения | includes() |
| Свойство размера | size | length |
| Перебор элементов | forEach, for…of | for...of, forEach |
| Применение | Уникальные значения, проверка наличия | Списки, упорядоченные данные |
