Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Map JS: Коллекции

В этом уроке мы познакомимся с ассоциативным массивом, а также разберем его преимущества и недостатки. Еще научимся работать с ним в языке JavaScript.

Map как объект

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

Вспомним JavaScript-объект:

const person = {
  firstName: 'Alan',
  lastName: 'Kay',
};

person.firstName; // Alan
person['firstName']; // Alan

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

Преимущества Map

Использование квадратных скобок дает несколько преимуществ:

  • Динамическое обращение
  • Динамическое обновление
  • Итерация

Разберем их подробнее.

Динамическое обращение

Мы можем динамически обращаться к свойствам или ключам через переменную, в которой хранится имя ключа, вместо обращения к свойству через точку. Например:

const person = {
  firstName: 'Alan',
  lastName: 'Kay',
};

const key = 'lastName';
person[key]; // Kay

Внутри квадратных скобок конструкция [key] ожидает выражение. Это может быть что угодно, например, мы передаем константу key, которая внутри содержит строку. Так мы получаем доступ к внутреннему значению.

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

Динамическое обновление

Так же как и с динамическим обращением вместо обновления свойства через точку мы можем делать то же самое через квадратные скобки:

const person = {
  firstName: 'Alan',
  lastName: 'Kay',
};

person['firstName'] = 'John';
// person.firstName = 'John';

const propName = 'lastName';
person[propName] = 'King';

В этом случае синтаксис практически не меняется.

Мы используем внутри не литерал, а переменную. Она в себе содержит имя, к свойству которого мы обращаемся.

Итерация

Для итерации по свойствам объекта в JavaScript есть методы, которые находятся не внутри самого объекта.

Чтобы итерировать, мы можем воспользоваться конструктором Object и вызвать у него метод keys, который возвращает нам ключи переданного объекта:

const person = {
  firstName: 'Alan',
  lastName: 'Kay',
};

Object.keys(person).forEach((propName) => console.log(person[propName]));

// Alan
// Kay

На выходе конструкции Object.keys(person) у нас получается массив.

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

Например, распечатываем все значения. Мы обращаемся к нашему объекту, в квадратных скобках указываем propName — переменная, содержащая ключ, который был извлечен из person. Как раз здесь проявляется динамическая природа квадратных скобок и ее удобства. Через точку у нас бы не получилось так сделать.

Есть и другой способ:

const person = {
  firstName: 'Alan',
  lastName: 'Kay',
};

Object.values(person).forEach((value) => console.log(value));

// Alan
// Kay

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

Недостатки Map

У объектов, как и у ассоциативных массивов, есть определенные недостатки, часть из которых довольно критические:

  • Дополнительные свойства
  • Ключи только строки и символы
  • Определение размера

Разберем их подробнее.

Дополнительные свойства

Когда мы ставим Object, у него есть большое количество свойств, которые даются ему по наследству. Эти свойства в большинстве случаев являются функциями:

const obj = {};
console.log(obj.valueOf);
// [Function: valueOf]

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

Ключи только строки и символы

Допустим, мы создали такой объект и распечатали его:

const obj = { 3: 'value'};
// { '3': 'value' }

В итоге тройка превратилась в строку. То есть внутри произошло преобразование. В работе это может быть неудобно.

Определение размера

Object не дает определить размер. Поэтому можно сделать так:

Object.keys(obj).length;

Мы обращаемся черезObject.keys(), достаем все ключи и вычисляем длину. Это не очень удобный способ вычислять размер объекта.

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

Тип Map

Map — это отдельный тип. Если сделать на нем new без переданных аргументов, то можно получить объект, с которым можно дальше работать:

const map = new Map();

При этом мы можем передать аргумент, который внутри станет ключевым значением:

new Map([[key, value], [key2, value2]]

Это массив массива, в котором каждый массив — это элемент из двух пар: ключ и значение. Внутри он превращается в [key, value]. Как там все хранится? мы не знаем, но у нас есть интерфейс, которым достаточно просто пользоваться.

Установка нового значения происходит через set:

// Принимается два параметра key и value
map.set('key', 'value');
map.set(10, 'another value');

// Смотрим размер
map.size; // 2

// Получаем значение обратного
map.get('key'); // value
map.get(10); // another value

Этот простой интерфейс позволяет работать и не переживать о перечисленных недостатках.

Map как коллекция

Если мы хотим работать с Map как с коллекцией, то для этого он дает из коробки несколько методов:

map.keys();
map.values();
map.entries(); // [[key, value], [key2, value2]];

entries() — это новый метод, который возвращает ту структуру, которая ожидается на вход в конструктор.

Еще у Map есть свойство forEach:

map.forEach((value, key) => console.log(key, value));

Нам не нужно получать key, value и как-то его обходить. Мы просто передаем в forEach функцию, которая принимает key, value. Это достаточно удобно для большинства моментов, где нам нужно обрабатывать Map.

Выводы

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

Еще мы научились создавать объект типа Map, а также работать с ним как с коллекциями. Для последнего можно использовать методы keys, values и entries.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»