JavaScript Map: хранение и поиск пар ключ-значение

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

Пример JavaScript Map для хранения пар ключ-значение

Вывод:

Результат появится здесь...

Вывод:

95
false
2

Как работает этот пример

  1. new Map() создает пустую коллекцию map. Вызов Map() без new вызывает TypeError.
  2. set добавляет пару ключ-значение и возвращает экземпляр Map, поэтому можно делать цепочки вызовов, например map.set("a", 1).set("b", 2). Если вызвать set с существующим ключом, значение перезапишется без изменения позиции ключа в порядке обхода.
  3. get возвращает сохраненное значение или undefined, если ключа нет. Используйте has, чтобы отличить отсутствующий ключ от ключа, который явно записан со значением undefined.
  4. size показывает текущее количество записей, в отличие от объектов, где нужно вычислять Object.keys(obj).length.

Частые ошибки при использовании JavaScript Map

Использование синтаксиса скобок вместо set/get:

Неправильно:

const map = new Map();
map["ключ"] = "значение";
console.log(map.get("ключ")); // undefined

Правильно:

const map = new Map();
map.set("ключ", "значение");
console.log(map.get("ключ")); // "значение"

Синтаксис скобок задает свойство объекта у экземпляра Map, а не запись Map. Методы get, has и свойство size это игнорируют.

Ожидание структурного равенства для ключей-объектов:

Неправильно:

const map = new Map();
map.set({id: 1}, "анна");
console.log(map.get({id: 1})); // undefined

Правильно:

const key = {id: 1};
map.set(key, "анна");
console.log(map.get(key)); // "анна"

Map использует алгоритм SameValueZero для сравнения ключей. Для объектов это означает сравнение по ссылке: два одинаковых на вид объектных литерала считаются разными ключами.

JavaScript Map vs Object

MapObject
Типы ключейЛюбые значения (объекты, функции, примитивы)Только строки и символы
Порядок обходаПорядок вставки (гарантирован)В основном порядок вставки, но целочисленные ключи сортируются первыми
Размерmap.sizeObject.keys(obj).length
Коллизии с прототипомНетКлючи могут перекрыть toString, constructor и т. д.
JSON-сериализацияВручную через Object.fromEntriesВстроено в JSON.stringify

Используйте Map, когда ключи не строки, записи часто добавляются и удаляются или вы храните недоверенные ключи. Используйте обычный объект для записей с фиксированной структурой или данных, которым нужна сериализация в JSON. Если нужен объект, но вы хотите избежать коллизий с ключами прототипа, используйте Object.create(null) как базовый объект.

FAQ

Сохраняет ли JavaScript Map порядок вставки?

Да. Map итерирует записи в порядке их первого добавления. Вызов set() для существующего ключа обновляет значение, но сохраняет исходную позицию. Если удалить ключ и добавить его снова, он переместится в конец.

Можно ли использовать объекты как ключи в JavaScript Map?

Да, но Map сравнивает ключи-объекты по ссылке, а не по структуре. Два разных объекта с одинаковыми свойствами считаются разными ключами. Сохраните ссылку в переменную и используйте одну и ту же ссылку в set и get.

Как преобразовать JavaScript Map в объект или JSON?

Вызовите Object.fromEntries(map), чтобы получить обычный объект, это работает, когда все ключи строки или символы. Для нестроковых ключей сериализуйте массив записей: JSON.stringify([...map]).

В чем разница между JavaScript Map и функцией JavaScript map()?

Map это коллекция ключ-значение для хранения и получения данных. Функция JavaScript map() (Array.prototype.map) это метод массива, который возвращает новый массив, применяя колбэк к каждому элементу. Название общее, назначение разное.