JavaScript Map и Set
В этой главе вы узнаете о Map и Set в JavaScript — структурах данных, которые расширяют возможности языка и упрощают решение типовых задач.
В этой главе рассматриваются две коллекции с ключами, появившиеся в современном JavaScript: Map (пары «ключ — значение») и Set (уникальные значения). Вы узнаете, что они делают, когда использовать их вместо обычных object и array, как перебирать их элементы, а также изучите практические паттерны — например, удаление дубликатов из array или построение счётчика частот.
JavaScript Map
Map — это коллекция пар «ключ — значение», во многом похожая на обычный object, но с важными отличиями, которые делают её предпочтительным выбором во многих ситуациях.
Map и обычный object: когда использовать Map
Используйте Map вместо обычного object, если:
- Ключи — не string. Ключи object всегда приводятся к string (или символам). Map позволяет использовать в качестве ключа любое значение: object, функции, числа и даже
NaN. - Вы часто добавляете и удаляете записи. Map оптимизирован для частых вставок и удалений, а
map.sizeсразу возвращает количество элементов (для object нужноObject.keys(obj).length). - Нужен гарантированный порядок обхода. Map всегда итерируется в порядке вставки.
- Хотите избежать коллизий с прототипом. Обычный object наследует ключи вроде
toStringиconstructor; у Map таких встроенных ключей нет, поэтому пользовательские ключи никогда с ними не пересекутся.
Используйте обычный object, когда данные имеют фиксированную, заранее известную структуру (запись), или когда требуется JSON-сериализация — JSON.stringify работает с object, но не с Map.
Создание Map и работа с ней
Для создания Map используйте new Map(). Поддерживаются следующие методы и свойства:
map.set(key, value): Добавляет или обновляет пару «ключ — значение». Возвращает Map, поэтому вызовы можно цепочкой.map.get(key): Возвращает значение по ключу (undefined, если ключ отсутствует).map.has(key): Возвращаетtrue, если ключ существует.map.delete(key): Удаляет пару «ключ — значение».map.clear(): Удаляет все элементы.map.size: Количество пар «ключ — значение».
Поскольку set() возвращает Map, вызовы можно выстраивать в цепочку:
Использование любого значения в качестве ключа
В отличие от object, Map хранит ключи в исходном виде. Число 1 и string "1" — это разные ключи; object и функции тоже могут быть ключами (сравниваются по ссылке):
Итерация по Map
Map перебирается в порядке вставки и предоставляет три метода-итератора, а также forEach:
map.keys()— итерируемый объект ключей.map.values()— итерируемый объект значений.map.entries()— итерируемый объект пар[key, value](используется по умолчанию, поэтомуfor...of mapработает напрямую).map.forEach((value, key) => ...)— выполняет колбэк для каждого элемента.
Преобразование между Map и object
Map можно создать из записей object и обратно преобразовать в object:
JavaScript Set
Set — это коллекция уникальных значений: каждое значение может встречаться только один раз. Set тесно связан с array, но не содержит дубликатов и не поддерживает доступ по индексу.
Set и array: когда использовать Set
Используйте Set вместо array, если:
- Уникальность важна. Set автоматически отклоняет дубликаты, поэтому не нужно проверять перед добавлением.
- Вы часто проверяете наличие элемента.
set.has(value)работает быстро и читается чисто, тогда какarray.includes(value)каждый раз просматривает весь array.
Оставайтесь с array, если вам нужны индексный доступ, дубликаты или методы array вроде map/filter/reduce. (Вы всегда можете конвертировать между ними.)
Работа с Set
new Set(iterable): Создаёт Set, опционально из array или любого итерируемого объекта.set.add(value): Добавляет значение (возвращает Set, вызовы можно цепочкой). Дубликаты игнорируются.set.has(value): Возвращаетtrue, если значение присутствует.set.delete(value): Удаляет значение.set.size: Количество значений.set.clear(): Удаляет все элементы.
Удаление дубликатов из array (основное применение)
Наиболее распространённая причина использовать Set — удалить дубликаты из array. Разверните Set обратно в array с помощью [...new Set(arr)]:
Итерация по Set
Set перебирается в порядке вставки и поддерживает for...of и forEach:
Объединение, пересечение и разность
Set упрощает классические операции над множествами. В современных движках есть встроенные методы set.union(), set.intersection() и set.difference(), но вот переносимый подход с использованием array:
Реальный сценарий: счётчик частоты слов
Этот пример показывает, почему Map часто выигрывает у обычного object. Мы считаем, сколько раз каждое слово встречается в предложении. С Map ключи остаются настоящими string-значениями, size доступен мгновенно, и нет риска коллизии слова с унаследованным свойством:
И Map, и Set являются итерируемыми объектами, поэтому они работают с for...of, оператором расширения (...) и деструктуризацией. Кроме того, JavaScript предоставляет WeakMap и WeakSet, которые позволяют собирать свои ключи сборщиком мусора. Подробнее читайте на нашей странице JavaScript WeakMap и WeakSet.
Шпаргалка по методам
Map
| Операция | Код |
|---|---|
| Создать | new Map() или new Map(Object.entries(obj)) |
| Добавить / обновить | map.set(key, value) (цепочкой) |
| Прочитать | map.get(key) |
| Проверить | map.has(key) |
| Удалить | map.delete(key) |
| Количество | map.size |
| Итерировать | for (let [k, v] of map), map.keys(), map.values(), map.entries(), map.forEach() |
| В object | Object.fromEntries(map) |
Set
| Операция | Код |
|---|---|
| Создать | new Set() или new Set(array) |
| Добавить | set.add(value) (цепочкой, дубликаты игнорируются) |
| Проверить | set.has(value) |
| Удалить | set.delete(value) |
| Количество | set.size |
| Итерировать | for (let v of set), set.forEach() |
| Убрать дубликаты | [...new Set(array)] |
Практическое правило: используйте Map, когда нужны ключи-данные с не-string ключами, частые обновления или гарантированный порядок; используйте Set, когда нужна коллекция уникальных значений с быстрой проверкой наличия. Во всех остальных случаях обычные object и array по-прежнему остаются правильным инструментом.