Map  – коллекция пар ключ-значение.

Объект содержит пары ключ-значение и запоминает исходный порядок вставки ключей. Любое значение (как объекты, так и примитивные значения) может использоваться либо как ключ, либо как значение.

Map хранит в себе данные, где в виде ключа могут быть: строки, цифры, булево значение.

Например:

let map = new Map()
map.set("1", "str1") // строка в качестве ключа
map.set(1, "num1") // цифра как ключ
map.set(true, "bool1") // булево значение как ключ
// помните, обычный объект Object приводит ключи к строкам? // Map сохраняет тип ключей, так что в этом случае сохранится 2 разных значения:
 
alert(map.get(1)) // "num1"
alert(map.get("1")) // "str1"
alert(map.size) // 3`

Методы и свойства:

  • new Map([iterable]) – создаёт коллекцию, можно указать перебираемый объект (обычно массив) из пар [ключ,значение] для инициализации.
  • map.set(key, value) – записывает по ключу key значение value.
  • map.get(key) – возвращает значение по ключу или undefined, если ключ key отсутствует.
  • map.has(key) – возвращает true, если ключ key присутствует в коллекции, иначе false.
  • map.delete(key) – удаляет элемент по ключу key.
  • map.clear() – очищает коллекцию от всех элементов.
  • map.size – возвращает текущее количество элементов.

Отличия от обычного объекта Object:

  • Что угодно может быть ключом, в том числе и объекты.
  • Есть дополнительные методы, свойство size. Как мы видим, в отличие от объектов, ключи не были приведены к строкам. Можно использовать любые типы данных для ключей.
Особенности использования map[key]

map[key] это не совсем правильный способ использования Map

Хотя map[key] также работает, например, мы можем установить map[key] = 2, в этом случаеmap рассматривался бы как обычный JavaScript объект, таким образом это ведёт ко всем соответствующим ограничениям (только строки/символьные ключи и так далее). Поэтому нам следует использовать методы mapsetget и так далее.

Map может использовать объекты в качестве ключей

Например:

let john = { name: "John" };  // давайте сохраним количество посещений для каждого пользователя let visitsCountMap = new Map();  // объект john - это ключ для значения в объекте
Map visitsCountMap.set(john, 123);
alert(visitsCountMap.get(john)); // 123`

Использование объектов в качестве ключей – одна из наиболее заметных и важных функций Map. Это то что невозможно для Object. Строка в качестве ключа в Object – это нормально, но мы не можем использовать другой Object в качестве ключа в Object.

Давайте попробуем заменить Map на Object:

let john = { name: "John" }
let ben = { name: "Ben" }
let visitsCountObj = {} // попробуем использовать объект  visitsCountObj[ben] = 234; // пробуем использовать объект ben в качестве ключа visitsCountObj[john] = 123; // пробуем использовать объект john в качестве ключа, при этом объект ben будет замещён  _// Вот что там было записано!
alert(visitsCountObj["[object Object]"]) // 123_`

Так как visitsCountObj является объектом, он преобразует все ключи Object, такие как john и ben, в одну и ту же строку "[object Object]". Это определенно не то, чего мы хотим.

Как объект Map сравнивает ключи

Чтобы сравнивать ключи, объект Map использует алгоритм SameValueZero. Это почти такое же сравнение, что и === , с той лишь разницей, что NaN считается равным NaN. Так что NaN также может использоваться в качестве ключа.

Этот алгоритм не может быть заменён или модифицирован.

Цепочка вызовов

Каждый вызов map.set возвращает объект map, так что мы можем объединить вызовы в цепочку:

map.set("1", "str1")
	.set(1, "num1")
	.set(true, "bool1");`

Для перебора коллекции Map есть 3 метода:

  • map.keys() – возвращает итерируемый объект по ключам,
  • map.values() – возвращает итерируемый объект по значениям,
  • map.entries() – возвращает итерируемый объект по парам вида [ключ, значение], этот вариант используется по умолчанию в for..of.

Например:

let recipeMap = new Map([
  ["огурец", 500],
  ["помидор", 350],
  ["лук", 50],
])
// перебор по ключам (овощи)
for (let vegetable of recipeMap.keys()) {
  alert(vegetable) // огурец, помидор, лук
} // перебор по значениям (числа)
 
for (let amount of recipeMap.values()) {
  alert(amount) // 500, 350, 50
} // перебор по элементам в формате [ключ, значение]
 
for (let entry of recipeMap) {
  // то же самое, что и recipeMap.entries()
 
  alert(entry) // огурец,500 (и так далее)
}
Используется порядок вставки

В отличие от обычных объектов Object, в Map перебор происходит в том же порядке, в каком происходило добавление элементов.

Кроме этого, Map имеет встроенный метод forEach, схожий со встроенным методом массивов Array:

// выполняем функцию для каждой пары (ключ, значение)
 
recipeMap.forEach((value, key, map) => {
	alert(`${key}: ${value}`); // огурец: 500 и так далее });``

Назад