Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос нашим менторам. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Map

Создание объекта типа Map

// Создание пустого объекта
const map = new Map();

При этом сам map является обычным объектом:

map instanceof Object // true
map instanceof Map // true

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

Иногда бывает нужно создать Map для уже существующих данных. Такой способ работы также предусмотрен через конструктор. Правда в этом случае придется подготовить данные определенным способом:

const map = new Map([['key', 'value'], ['anotherKey', 'anotherValue']]);

Основные функции для работы с Map

К ним относятся get, set и has.

has нужен для проверки наличия ключа:

const map = new Map()
map.set('key', 'value');
map.get('key'); // value
map.has('key'); // true

// Если ключа нет, то вернется undefined
map.get('unknown'); // undefined
map.has('unknown'); // false

Map поддерживает fluent интерфейс. Функция set возвращает сам Map. Таким образом можно строить цепочки:

const map = new Map();
map.set('key', 'value').set('anotherKey', 'anotherValue');

Подробнее про fluent интерфейс расскажем чуть позже в отдельном уроке курса.

Для удаления из Map служит функция delete, которая принимает на вход имя ключа. Функция clear поступает более радикально: удаляет все элементы из Map-объекта. Крайне не рекомендую строить свои алгоритмы таким образом, чтобы пришлось изменять объекты удалением ключей. Такой код сложен в отладке и понимании.

Перебор Map-объектов

Цикл for...of

Ещё из полезных функций есть keys и values. Они возвращают специальный объект-итератор, чем-то отдалённо похожий на массив ключей или значений. Для возможности применить функции высшего порядка, такие как filter/reduce/map, всё же придётся производить непосредственное преобразование к массиву: Array.from(map).

Более подробно об итераторах мы будем говорить в одном из будущих курсов. А сейчас просто рассмотрим их применение. Они используются для перебора ключей/значений/записей Map-объекта с помощью цикла for...of.

Разберём как это работает на примере сконструированного Map-объекта person:

const person = new Map([['name', 'John'], ['surname', 'Doe'], ['age', 50]]);

Давайте посмотрим какие вообще есть свойства у person:

// создание итератора по ключам
// имя константы может быть любым, мы выбрали 'keys'
const keys = person.keys();

// перебор ключей
for (const key of keys) {
  console.log(key);
}

// name
// surname
// age

Теперь пробежимся по значениям Map-объекта person:

// создание итератора по значениям
const values = person.values();

// перебор значений
for (const value of values) {
  console.log(value);
}

// John
// Doe
// 50

Можно перебирать сразу целые записи, то есть пары "ключ-значение":

// создание итератора по записям
const entries = person.entries();

// перебор записей
for (const entry of entries) {
  console.log(entry);
}

// [ 'name', 'John' ]
// [ 'surname', 'Doe' ]
// [ 'age', 50 ]

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

Метод forEach

У Map-объектов также есть метод forEach, который позволяет удобно сделать перебор ключей и значений. Этот метод вызывается на объекте и принимает на вход callback-функцию. На каждой итерации эта callback-функция принимает ключ и значение очередной записи объекта, поэтому надо предусмотреть для них в сигнатуре функции соответствующие параметры (в примере ниже, это параметры value и key):

const person = new Map([['name', 'John'], ['surname', 'Doe'], ['age', 50]]);

// подготавливаем callback-функцию
const cb = (value, key) => console.log(`${key} - ${value}`);

// делаем обход Map-объекта
person.forEach(cb);

// name - John
// surname - Doe
// age - 50

Порядок перебора

Обратите внимание, что при итерировании Map-объектов происходит перебор свойств в порядке их добавления. Что не может гарантировать обычный объект типа object.

Отличие от объекта

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

const obj = {};
obj.hasOwnProperty('key'); // false

// Перезаписываем (случайно или специально)
obj['hasOwnProperty'] = 'value';
obj.hasOwnProperty('key'); // => TypeError: obj.hasOwnProperty is not a function

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

const map = new Map();
map.hasOwnProperty('key'); // false
map.set('hasOwnProperty', 'value');
map.hasOwnProperty('key'); // false

Из того, что Map хранит свойства особым образом, следует то, что им нельзя пользоваться как обычным объектом (технически конечно можно, но тогда непонятно зачем используется Map). Например установленные свойства через set невозможно получить прямым доступом к свойствам объекта. Точно такая же ситуация и при чтении. Установленное через обычные свойства нельзя получить через get.

const map = new Map();
map['key'] = 'value';
map.get('key'); // undefined
map.set('key2', 'value2');
map['key2']; // undefined

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

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

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

Для полного доступа к курсу нужна профессиональная подписка

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

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

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

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг». Защита от спама reCAPTCHA «Конфиденциальность» и «Условия использования».

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

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

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

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг». Защита от спама reCAPTCHA «Конфиденциальность» и «Условия использования».