← Назад к вопросам

Что может быть ключами в Set?

1.8 Middle🔥 191 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ключи и значения в Set

В JavaScript Set — это коллекция уникальных значений, где каждый элемент может встречаться только один раз. Вопрос о ключах в Set является отличным поводом углубиться в его внутреннее устройство и отличия от Map.

Короткий ответ

В Set нет понятия "ключей" в классическом понимании, как в Map или объектах. Сам элемент коллекции одновременно является и ключом, и значением. Это фундаментальное отличие от Map, где ключи и значения — это отдельные сущности.

Детальное объяснение

1. Внутренняя механика Set

Когда вы добавляете значение в Set, JavaScript использует алгоритм "SameValueZero" для сравнения на уникальность. Этот алгоритм похож на строгое равенство (===), но с особым отношением к NaN.

const mySet = new Set();

mySet.add(42); // Число
mySet.add("строка"); // Строка
mySet.add({ id: 1 }); // Объект
mySet.add([1, 2, 3]); // Массив

// Объекты сравниваются по ссылке, а не по содержимому
const obj = { name: "test" };
mySet.add(obj);
mySet.add(obj); // Не добавится - та же ссылка
mySet.add({ name: "test" }); // Добавится - новый объект, новая ссылка

console.log(mySet.size); // 6

2. Что может быть элементом (и условным "ключом") в Set?

Любой тип данных JavaScript может быть элементом Set:

  • Примитивы: String, Number, Boolean, undefined, null, Symbol
  • Ссылочные типы: Object, Array, Function, Map, другой Set
  • Специальные значения: NaN (в Set считается равным самому себе, в отличие от NaN === NaN)
const diverseSet = new Set();

// Примитивы
diverseSet.add(100); // Number
diverseSet.add("ключ"); // String  
diverseSet.add(true); // Boolean
diverseSet.add(undefined); // undefined
diverseSet.add(null); // null
diverseSet.add(Symbol("описание")); // Symbol

// Ссылочные типы
diverseSet.add(function() { console.log("функция"); }); // Function
diverseSet.add(new Map([["a", 1]])); // Map
diverseSet.add(new Set([1, 2])); // Set

// NaN обрабатывается особым образом
diverseSet.add(NaN);
diverseSet.add(NaN); // Не добавится второй раз!
console.log(diverseSet.has(NaN)); // true

3. Как работает идентификация элементов

Механизм идентификации элементов для проверки уникальности работает по-разному для разных типов:

  • Примитивы: сравниваются по значению

    const set1 = new Set();
    set1.add(5);
    set1.add(5); // Не добавится - значение уже есть
    set1.add("5"); // Добавится - строка "5" ≠ число 5
    
  • Объекты (включая массивы, функции): сравниваются по ссылке

    const set2 = new Set();
    set2.add([1, 2]);
    set2.add([1, 2]); // Добавится! Разные массивы = разные ссылки
    
    const arr = [3, 4];
    set2.add(arr);
    set2.add(arr); // Не добавится - та же ссылка
    

4. Отличие от Map и практические следствия

В Map есть четкое разделение:

const map = new Map();
map.set("ключ", "значение"); // Ключ и значение разделены

В Set это объединено:

const set = new Set();
set.add("элемент"); // "элемент" одновременно и ключ, и значение

Практическое следствие: у Set нет метода get() (как у Map), потому что для получения значения вам уже нужно иметь это значение. Вместо этого используется has() для проверки наличия.

5. Итерация и методы работы

Set предоставляет методы для работы с коллекцией, которые подтверждают отсутствие разделения на ключи и значения:

  • add(value) — добавляет элемент (являющийся своим же ключом)
  • has(value) — проверяет наличие элемента
  • delete(value) — удаляет элемент
  • forEach(callback) — вызывает функцию для каждого элемента
  • keys(), values(), entries() — методы для совместимости с Map, но keys() и values() возвращают одно и то же
const fruitSet = new Set(["яблоко", "банан", "апельсин"]);

// Все три метода дают одинаковый результат по содержанию
console.log([...fruitSet.keys()]);    // ["яблоко", "банан", "апельсин"]
console.log([...fruitSet.values()]);  // ["яблоко", "банан", "апельсин"]

// entries() возвращает пары [значение, значение]
console.log([...fruitSet.entries()]); // [["яблоко", "яблоко"], ["банан", "банан"], ...]

Вывод

Таким образом, вопрос "что может быть ключами в Set" технически некорректен, поскольку в Set нет отдельной концепции ключей. Правильнее говорить о типах данных, которые могут быть элементами Set. Эти элементы служат одновременно и идентификаторами для обеспечения уникальности (аналогично ключам), и несут полезную нагрузку (аналогично значениям). Эта особенность делает Set идеальным для задач удаления дубликатов и проверки принадлежности, где само значение достаточно для его идентификации в коллекции.

Что может быть ключами в Set? | PrepBro