Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Для чего использовал Set?
Set — это встроенная структура данных в JavaScript, которая хранит уникальные значения. Это мощный инструмент для многих сценариев разработки, от фильтрации дубликатов до оптимизации поиска.
Что такое Set?
Set — это коллекция уникальных значений. Если попытаться добавить дублированное значение, оно не будет добавлено.
// Создание Set
const set1 = new Set();
const set2 = new Set([1, 2, 3, 3, 4, 4]); // дубликаты игнорируются
console.log(set2); // Set(4) { 1, 2, 3, 4 }
console.log(set2.size); // 4
Основные методы Set
const colors = new Set();
// add() - добавить элемент
colors.add('red');
colors.add('blue');
colors.add('red'); // не добавится, уже есть
// has() - проверить наличие
console.log(colors.has('red')); // true
console.log(colors.has('green')); // false
// delete() - удалить элемент
colors.delete('red');
console.log(colors.has('red')); // false
// clear() - очистить
colors.clear();
console.log(colors.size); // 0
// Итерация
colors.add('red');
colors.add('blue');
colors.add('green');
colors.forEach(color => console.log(color)); // red, blue, green
for (const color of colors) {
console.log(color);
}
Кейс 1: Удаление дубликатов из массива
Это один из самых частых случаев использования Set:
// Проблема: в массиве есть дубликаты
const numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5];
// Решение 1: использовать Set
const uniqueNumbers = Array.from(new Set(numbers));
console.log(uniqueNumbers); // [1, 2, 3, 4, 5]
// Решение 2: через spread operator
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4, 5]
// Сравним с другими подходами
// filter + indexOf (медленнее)
const unique2 = numbers.filter((v, i) => numbers.indexOf(v) === i);
// Set работает быстрее благодаря O(1) поиску
Кейс 2: Проверка уникальности элементов
function hasUniqueElements(arr) {
return arr.length === new Set(arr).size;
}
console.log(hasUniqueElements([1, 2, 3])); // true
console.log(hasUniqueElements([1, 2, 2])); // false
Кейс 3: Пересечение массивов
function intersection(arr1, arr2) {
const set2 = new Set(arr2);
return arr1.filter(item => set2.has(item));
}
const array1 = [1, 2, 3, 4, 5];
const array2 = [3, 4, 5, 6, 7];
console.log(intersection(array1, array2)); // [3, 4, 5]
Кейс 4: Разница между двумя массивами
function difference(arr1, arr2) {
const set2 = new Set(arr2);
return arr1.filter(item => !set2.has(item));
}
const users1 = ['Иван', 'Петр', 'Мария'];
const users2 = ['Петр', 'Анна'];
console.log(difference(users1, users2)); // ['Иван', 'Мария']
Кейс 5: Отслеживание посещённых узлов (BFS/DFS)
function findPath(graph, start, end) {
const visited = new Set();
const queue = [start];
const parent = new Map();
while (queue.length > 0) {
const node = queue.shift();
if (node === end) {
// Восстанавливаем путь
const path = [];
let current = end;
while (current !== undefined) {
path.unshift(current);
current = parent.get(current);
}
return path;
}
if (!visited.has(node)) {
visited.add(node);
for (const neighbor of graph[node]) {
if (!visited.has(neighbor)) {
queue.push(neighbor);
parent.set(neighbor, node);
}
}
}
}
return null;
}
const graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
};
console.log(findPath(graph, 'A', 'F')); // ['A', 'B', 'E', 'F']
Кейс 6: Фильтрация уникальных пользователей в React
import { useState, useMemo } from 'react';
interface User {
id: number;
name: string;
email: string;
}
function UserList({ users }: { users: User[] }) {
// Получить уникальных пользователей по email
const uniqueUsers = useMemo(() => {
const seen = new Set();
return users.filter(user => {
if (seen.has(user.email)) {
return false;
}
seen.add(user.email);
return true;
});
}, [users]);
return (
<ul>
{uniqueUsers.map(user => (
<li key={user.id}>{user.name} ({user.email})</li>
))}
</ul>
);
}
Кейс 7: Сравнение производительности
// Проверка принадлежности элемента
// Массив O(n) при каждой проверке
const arr = [1, 2, 3, 4, 5, 100000];
console.time('Array');
for (let i = 0; i < 100000; i++) {
arr.includes(99999); // медленно
}
console.timeEnd('Array'); // ~50ms
// Set O(1) при каждой проверке
const set = new Set(arr);
console.time('Set');
for (let i = 0; i < 100000; i++) {
set.has(99999); // быстро
}
console.timeEnd('Set'); // ~5ms
Кейс 8: Отслеживание активных соединений (WebSocket)
class ConnectionManager {
#connections = new Set();
addConnection(id) {
this.#connections.add(id);
console.log(`Соединение добавлено. Всего: ${this.#connections.size}`);
}
removeConnection(id) {
this.#connections.delete(id);
console.log(`Соединение удалено. Осталось: ${this.#connections.size}`);
}
hasConnection(id) {
return this.#connections.has(id);
}
broadcastMessage(message) {
for (const connectionId of this.#connections) {
this.sendToConnection(connectionId, message);
}
}
sendToConnection(id, message) {
console.log(`Отправка ${message} подключению ${id}`);
}
}
const manager = new ConnectionManager();
manager.addConnection('user1'); // Соединение добавлено. Всего: 1
manager.addConnection('user2'); // Соединение добавлено. Всего: 2
manager.broadcastMessage('Hello!'); // отправит двум пользователям
manager.removeConnection('user1'); // Соединение удалено. Осталось: 1
Кейс 9: Кэширование с ограничением размера
class LRUCache {
#cache = new Map();
#maxSize;
constructor(maxSize = 100) {
this.#maxSize = maxSize;
}
get(key) {
if (!this.#cache.has(key)) return undefined;
const value = this.#cache.get(key);
// Переместить в конец (используется позже)
this.#cache.delete(key);
this.#cache.set(key, value);
return value;
}
set(key, value) {
if (this.#cache.has(key)) {
this.#cache.delete(key);
} else if (this.#cache.size >= this.#maxSize) {
// Удалить самый старый (первый элемент)
const firstKey = this.#cache.keys().next().value;
this.#cache.delete(firstKey);
}
this.#cache.set(key, value);
}
}
const cache = new LRUCache(3);
cache.set('a', 1);
cache.set('b', 2);
cache.set('c', 3);
cache.set('d', 4); // удалит 'a'
Кейс 10: Дебаунсинг с отслеживанием активных операций
class DebounceManager {
#pending = new Set();
debounce(key, fn, delay = 300) {
// Отменить предыдущую операцию
if (this.#pending.has(key)) {
clearTimeout(this.#pending.get(key));
}
const timeoutId = setTimeout(() => {
fn();
this.#pending.delete(key);
}, delay);
this.#pending.set(key, timeoutId);
}
cancelAll() {
for (const timeoutId of this.#pending.values()) {
clearTimeout(timeoutId);
}
this.#pending.clear();
}
}
const manager = new DebounceManager();
// Использование при обновлении текста
manager.debounce('search', () => {
console.log('Поиск выполняется...');
}, 500);
Set vs Map vs Object
| Структура | Когда использовать | Производительность |
|---|---|---|
| Set | Уникальные значения, O(1) проверка | Отличная |
| Array | Упорядоченные данные, индекс доступ | Хорошая для итерации |
| Map | Пары ключ-значение, объекты как ключи | Отличная |
| Object | Простые структуры данных | Хорошая для строк как ключи |
Практические советы
// 1. Используй Set для проверки наличия элемента (быстро)
const subscribed = new Set(userIds);
if (subscribed.has(userId)) { /* ... */ }
// 2. Используй Set для деликатных данных (токены, UUID)
const invalidTokens = new Set();
invalidTokens.add(token);
// 3. Используй Set в алгоритмах (граф, поиск в ширину)
const visited = new Set();
// 4. Set может хранить любые значения (не только примитивы)
const objSet = new Set();
objSet.add({ id: 1 });
objSet.add([1, 2, 3]);
objSet.add(function() {});
// 5. Используй WeakSet для объектов, которые могут быть удалены
const observers = new WeakSet();
Set — это необходимый инструмент в JavaScript для любого разработчика. Знание правильных случаев использования Set значительно улучшит производительность и чистоту кода.