Map в JavaScript

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

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

Как создать Map

let userRoles = new Map()

После создания коллекция будет пустой. Добавить данные можно с помощью метода set().

let userRoles = new Map()

userRoles.set('admin', 'full access')
userRoles.set('editor', 'can edit')

В первом аргументе указывается ключ, во втором - значение, которое нужно сохранить.

Map также можно создать сразу с начальными данными. Для этого передается массив, где каждый элемент - это пара [key, value].

let userRoles = new Map([
  ['admin', 'full access'],
  ['editor', 'can edit'],
  ['guest', 'read only'],
])

Получение данных из Map

Чтобы получить значение по ключу, используется метод get().

let userRoles = new Map([
  ['admin', 'full access'],
  ['editor', 'can edit'],
])

userRoles.get('admin') // 'full access'

Если такого ключа нет, метод вернет undefined.

userRoles.get('guest') // undefined

Проверить наличие ключа можно с помощью метода has().

userRoles.has('editor') // true
userRoles.has('guest') // false

Если значение может быть undefined, лучше проверять ключ через has(), а не только смотреть на результат get().

Методы для работы с Map

set()

Добавляет новую пару ключ - значение или обновляет значение, если такой ключ уже есть.

let settings = new Map()

settings.set('theme', 'dark')
settings.set('theme', 'light')

settings.get('theme') // 'light'

delete()

Удаляет элемент по ключу и возвращает true, если элемент был найден.

let settings = new Map([
  ['theme', 'dark'],
  ['language', 'ru'],
])

settings.delete('theme') // true
settings.has('theme') // false

clear()

Удаляет все элементы из коллекции.

settings.clear()

settings.size // 0

size

Свойство size хранит количество элементов в Map.

let settings = new Map([
  ['theme', 'dark'],
  ['language', 'ru'],
])

settings.size // 2

Ключи в Map

В обычном объекте имена свойств чаще всего являются строками. В Map ключом может быть строка, число, объект, массив, функция или другое значение.

let user = { name: 'Alex' }
let visits = new Map()

visits.set(user, 5)

visits.get(user) // 5

С объектами важно учитывать ссылку. Если создать другой объект с такими же свойствами, для Map это будет уже другой ключ.

let firstUser = { name: 'Alex' }
let secondUser = { name: 'Alex' }

let visits = new Map()

visits.set(firstUser, 5)

visits.get(secondUser) // undefined

Перебор Map

Map хранит элементы в порядке их добавления. Перебрать коллекцию можно циклом for…of.

let userRoles = new Map([
  ['admin', 'full access'],
  ['editor', 'can edit'],
  ['guest', 'read only'],
])

for (let [role, access] of userRoles) {
  console.log(role, access)
}

Также можно отдельно получить ключи, значения или пары ключ-значение.

  • keys() - возвращает ключи;
  • values() - возвращает значения;
  • entries() - возвращает пары [key, value].

Эти методы возвращают перебираемые объекты. Если нужен обычный массив, можно использовать Array.from().

Array.from(userRoles.keys()) // ['admin', 'editor', 'guest']
Array.from(userRoles.values()) // ['full access', 'can edit', 'read only']
Array.from(userRoles.entries()) // [['admin', 'full access'], ...]

Метод forEach() тоже работает с Map.

userRoles.forEach((access, role) => {
  console.log(`${role}: ${access}`)
})

В forEach() первым параметром приходит значение, вторым - ключ.

Map и обычный объект

Обычный объект удобно использовать, когда мы описываем сущность с понятными свойствами: пользователя, товар, настройки страницы.

let user = {
  name: 'Alex',
  age: 25,
  city: 'Moscow',
}

Map удобнее, когда данные больше похожи на коллекцию: их нужно часто добавлять, удалять, перебирать и получать по ключу.

let cart = new Map()

cart.set('book', 2)
cart.set('pen', 5)

cart.get('book') // 2

Map и array.map()

Map и array.map() - это разные вещи. Map является коллекцией данных, а array.map() - методом массива, который создает новый массив на основе старого.

let prices = [100, 200, 300]

prices.map(price => price * 2) // [200, 400, 600]

Если нужно преобразовать массив, используется map(). Если нужно хранить пары ключ - значение, используется Map.

Итого

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