Skip to main content

Map проти об'єкта

Багато хто вважає, що Map і звичайний об'єкт {} це майже одне й те саме, але між ними є суттєві відмінності. Object це структура даних загального призначення для зберігання властивостей, ключі яких є рядками або символами, а Map це спеціалізована колекція для зберігання пар «ключ → значення» з ключами будь-якого типу і збереженням порядку вставки.

Теорія

TL;DR

  • Ключі об'єкта, це тільки рядки та символи, ключі Map, це будь-які значення.
  • Map завжди повертає елементи в порядку вставки, об'єкт сортує цілочислові ключі.
  • Розмір: Object.keys(obj).length проти простого map.size.
  • Map ітерабельний напряму через for...of, об'єкт, ні.
  • Map швидший при частих вставках і видаленнях.
  • Map не успадковує Object.prototype, тож немає конфліктів із toString чи hasOwnProperty.
  • Конвертація в обидва боки: new Map(Object.entries(obj)) і Object.fromEntries(map).

Швидкий приклад

javascript
const obj = {}; const map = new Map(); const keyObj = { id: 1 }; obj[keyObj] = 'object value'; map.set(keyObj, 'map value'); console.log(obj); // { "[object Object]": "object value" } console.log(map.get(keyObj)); // "map value"

В об'єкті ключ перетворився на рядок "[object Object]", а в Map залишився справжнім об'єктом. Якби ми додали другий об'єкт як ключ, в obj він би просто перезаписав перший запис, бо рядок вийшов би той самий.

Тип ключів

ОсобливістьObjectMap
КлючіТільки рядки або символиБудь-які типи (рядки, числа, об'єкти, функції тощо)

Це найважливіша практична різниця: лише Map дозволяє використати об'єкт або функцію як ключ і таким чином «прив'язати» дані до конкретного екземпляра.

Порядок, розмір і перебір

Порядок ключів.

ОсобливістьObjectMap
Порядок ключівЧастково гарантований (ES6 і новіші)Завжди зберігається

Map завжди повертає елементи в порядку вставки, а об'єкт поводиться інакше з числовими ключами:

javascript
const obj = { 2: 'b', 1: 'a' }; console.log(Object.keys(obj)); // ["1", "2"] (числа сортуються за зростанням)
javascript
const map = new Map([[2, 'b'], [1, 'a']]); console.log([...map.keys()]); // [2, 1] (порядок зберігається)

Розмір.

ОсобливістьObjectMap
РозмірObject.keys(obj).lengthmap.size
javascript
const map = new Map([['a', 1], ['b', 2]]); console.log(map.size); // 2

Різниця не лише в зручності: Object.keys() створює проміжний масив, а size це просто читання лічильника.

Ітерабельність.

ОсобливістьObjectMap
Перебирається напрямуНіТак
javascript
const map = new Map([['x', 10], ['y', 20]]); for (const [key, value] of map) { console.log(key, value); } // x 10 // y 20

Для об'єкта доведеться викликати Object.keys(), Object.entries() і подібні методи.

Продуктивність і прототип

ОсобливістьObjectMap
Часті вставки та видаленняПовільнішеШвидше
Ітерації по елементахНезручноЗручно через for...of

Map оптимізований саме під часті додавання, видалення і обхід, тоді як рушій оптимізує об'єкти під стабільну «форму» з відомим набором полів.

ОсобливістьObjectMap
Успадковує від Object.prototypeТакНі
Може конфліктувати з методами (toString, hasOwnProperty)ТакНі

У Map немає «сміття» у вигляді вбудованих методів, тому будь-який ключ можна використовувати безпечно. В об'єкті ключ "hasOwnProperty" або "__proto__" здатен зламати логіку перевірок.

Перетворення між ними

javascript
const obj = { a: 1, b: 2 }; const map = new Map(Object.entries(obj)); console.log(map); // Map(2) { 'a' => 1, 'b' => 2 } const backToObj = Object.fromEntries(map); console.log(backToObj); // { a: 1, b: 2 }

Object.entries() і Object.fromEntries() дозволяють легко конвертувати туди й назад. Це ж і спосіб серіалізувати Map, бо напряму JSON.stringify(map) дає {}.

Що і коли використовувати

ВикористовуйКоли
Objectструктура даних із фіксованими властивостями (наприклад, модель користувача)
Mapдинамічні ключі, ключі будь-якого типу, кеш, часті операції додавання та видалення

Коротко:

ОсобливістьObjectMap
Тип ключіврядок або символбудь-який тип
Порядок ключівчастково впорядкованийзберігається
Розміртреба рахувати вручну.size
Ітерабельністьчерез Object.keys()напряму (for...of)
Продуктивністьнижчавища
Застосуваннястатичні данідинамічні колекції

Типові помилки

  • Використовувати об'єкт як ключ звичайного об'єкта. Ключ мовчки стане рядком "[object Object]", і всі об'єкти зіллються в один запис.
  • Покладатися на порядок числових ключів об'єкта. Цілочислові ключі завжди сортуються за зростанням, незалежно від порядку вставки.
  • Писати map.length або map['key']. Перше це undefined, друге створює властивість поза колекцією; правильно, map.size і map.get('key').
  • Серіалізувати Map напряму. JSON.stringify(map) поверне {}, спочатку потрібен Object.fromEntries(map) або масив із [...map].
  • Брати Map скрізь «бо швидше». Для невеликої фіксованої моделі об'єкт зручніший: деструктуризація, скорочений запис, підтримка в JSON.
  • Забувати, що Map тримає ключі сильно. Об'єкти-ключі не зникнуть із пам'яті, поки живий сам Map, для слабких посилань є WeakMap.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.