Карти проти об’єктів у ES6, коли використовувати?


83

Посилання: Карти MDN

Використовуйте карти над об’єктами, коли ключі невідомі до часу запуску, і коли всі ключі однакового типу та всі значення одного типу.

Використовуйте об’єкти, коли існує логіка, яка оперує окремими елементами.

Питання:

Який прикладний приклад використання Карт над об’єктами? зокрема, "коли ключі будуть невідомі до часу виконання?"

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));

Так, я це помітив. Як я встановив функцію як значення. @JonathanLonowski, чи можете ви придумати, коли я повинен це робити: (це важке мислення щодо випадків використання.
Matthew Harwood,

7
Ви можете використовувати його там, де ви говорите елемент DOM, з яким ви хочете пов’язати деякі дані за допомогою об’єкта. Замість того, щоб використовувати, скажімо, ідентифікатор елемента як ключ в об'єкті, ви можете використовувати сам елемент як ключ у Карті, щоб вам було байдуже, чи має елемент ідентифікатор (або будь-який інший унікальний ідентифікатор, крім посилання на об'єкт) ) чи ні.
RobG

1
@RobG лише невелике доповнення: у такому випадку це WeakMapтакож може бути корисним.
zerkms

1
Думаю, це пропонує використовувати об’єкти як / для записів, а Карти для будь-якого іншого відображення. Під записами я маю на увазі структуру даних із фіксованим набором полів, наприклад, об'єкт користувача, який має поля, nameі, idнаприклад.
Фелікс Клінг,

1
Коли я читав цю сторінку MDN, список випадків використання був набагато кориснішим, ніж цитований вами абзац. Звичайно, стосовно питання, поставленого у вашому заголовку.
CodingIntrigue

Відповіді:


51

Який прикладний приклад використання Карт над об’єктами?

Я думаю, ви вже дали один хороший приклад: Вам принаймні потрібно використовувати Maps, коли ви використовуєте об'єкти (включаючи об'єкти Function) як ключі.

зокрема, "коли ключі будуть невідомі до часу виконання?"

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

На відміну від цього, вам слід використовувати об’єкти, коли ви знаєте, якими та скільки властивостей має об’єкт під час написання коду - коли їх форма статична. Як сказав @Felix: коли вам потрібен запис . Хороший показник для необхідності - це те, коли поля мають різні типи, і коли вам ніколи не потрібно використовувати нотацію в дужках (або очікувати обмеженого набору імен властивостей).


1
Або з іншої точки зору: всякий раз, коли вам потрібно переглядати властивості вашого об’єкта на рівні даних (наприклад for..of), а не на рівні програми (наприклад for..in), використовуйте a Map. Більше інформації стосовно цих умов у цій відповіді .

Я додам в коментарі також той факт , що в будь-який момент ви не знаєте , який тип ключ буде і ви не очікуєте рядок в якості основних типів даних, а потім використовувати карту stackoverflow.com/questions/32600157 / ...
Carmine Tambascia

26

Я думаю, що у ES2015 залишаються Mapлише дві причини використовувати звичайні об’єкти:

  • Ви взагалі не хочете переглядати властивості типу об’єкта
  • або ви робите, але порядок властивостей не має значення, і ви можете відрізнити програму від рівня даних під час ітерації

Коли порядок власності є неважливим?

  • якщо у вас є лише одне значення та деякі функції, які мають бути явно пов’язані з ним (наприклад, Promise- який є проксі для майбутнього значення - та then/ catch)
  • якщо у вас є структура даних, схожа на структуру / запис, зі статичним набором властивостей, відомим під час "часу компіляції" (зазвичай структури / записи не можна повторити)

У всіх інших випадках ви можете розглянути можливість використання Map, оскільки воно зберігає порядок властивостей і відокремлює програму (усі властивості, присвоєні Mapоб’єкту) від рівня даних (усі записи в самому Mapсобі).

Які недоліки Map?

  • ви втрачаєте лаконічний синтаксис об’єкта
  • вам потрібні власні замінники для JSON.stringyfy
  • ви втрачаєте деструктуризацію, що в будь-якому випадку є більш корисним для статичних структур даних

Цей рядок мене дуже стосується: "це, мабуть, повільніше, ніж чисті об'єкти, схожі на хеш-карту". Я думав замінити всі свої об'єкти картами через покращення продуктивності. Але ви кажете, що це повільніше ...
mesqueeb

1
Ти маєш рацію. Mapшвидше за все, оскільки він базується виключно на хеші, тоді Objectяк трохи складніший. Дякую!

11

Використовуйте карти над об’єктами, коли ключі невідомі до часу запуску, і коли всі ключі однакового типу та всі значення одного типу.

Я не уявляю, чому хтось написав би щось таке очевидно неправильне. Слід сказати, що в наш час люди знаходять дедалі більше неправильного та / або сумнівного вмісту на MDN.

Ніщо в цьому реченні не є правильним. Основна причина використання карт - це коли вам потрібні об'єктно-оцінні ключі. Думка про те, що значення повинні бути однотипними, абсурдна - хоча, звичайно, вони можуть бути. Думка про те, що не слід використовувати об’єкти, коли ключі невідомі до часу запуску, однаково абсурдна.


1
Я не бачу, що такого абсурдного в ідеї? Коли вам потрібні колекції, вони, як правило, строго друкуються (звичайно, можуть бути винятки). Крім того, я вважаю, що більше не використовувати об’єкти для колекцій (коли Mapце можливо) є гарною порадою.
Бергі,

Те, що колекції, як правило, строго набираються, логічно відрізняється від твердження, що щось суворо набране має бути колекцією.

1
Так, я думаю, це висловлено трохи дивно, але ідея чудова. Я думаю, що вони думали, що "ключі невідомі до часу запуску" вже створює колекцію. Будь-яка ідея для кращої фрази?
Бергі,

1
Домовились. MDN має дуже хорошу документацію, але вони повинні дотримуватися документації API-файлів doc і не намагатися давати поради щодо програмування.
AlexG

5

Однією з різниць між Mapі Objectє:

Mapможе використовувати складний тип даних як свій ключ. подобається це:

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

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

Object, він приймає лише простий тип даних ( number, string) як свій ключ.

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}

2

Це питання є дублікатом але поки він не закритий, ось моя відповідь звідти :

На додаток до інших відповідей, я виявив, що Карти є більш громіздкими та багатослівними для роботи, ніж об’єкти.

obj[key] += x
// vs.
map.set(map.get(key) + x)

Це важливо, оскільки коротший код швидше читається, є більш виразним і краще зберігається в голові програміста .

Інший аспект: оскільки set () повертає карту, а не значення, неможливо зв’язати призначення.

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map

Налагодження карт також є більш болючим. Внизу ви насправді не можете побачити, які ключі є на карті. Для цього вам потрібно написати код.

Успіху в оцінюванні Map Iterator

Об'єкти можуть бути оцінені будь-якою IDE:

WebStorm оцінює об'єкт


6
Це взагалі не відповідає на запитання " Який прикладний приклад використання Карт над об'єктами? "
Бергі,

6
Будь ласка, не розміщуйте відповіді між собою. І ні, питання не є дублікатом.
Бергі,

1

Objects подібні до Maps тим, що обидва дозволяють встановлювати для ключів значення, отримувати ці значення, видаляти ключі та визначати, чи щось зберігається в ключі. Через це (і оскільки не було вбудованих альтернатив), Objects використовувались як Maps історично; однак існують важливі відмінності, які роблять використання Mapпереважним у певних випадках:

  • Ключами an Objectє Strings і Symbols, тоді як вони можуть мати будь-яке значення для a Map, включаючи функції, об'єкти та будь-який примітив.
  • Ключі Mapвпорядковані, тоді як ключі, додані до об’єкта, ні. Таким чином, при ітерації над ним Mapоб'єкт повертає ключі в порядку вставки.
  • Ви можете легко отримати розмір властивості Mapз sizeвластивістю, тоді як кількість властивостей у мусі Objectповинна визначатися вручну.
  • A Mapє ітераційним і, отже, може бути безпосередньо ітераційним, тоді як ітерація над a Objectвимагає отримання його ключів певним чином і ітерації над ними.
  • У An Objectє прототип, тому на карті є ключі за замовчуванням, які можуть зіткнутися з вашими ключами, якщо ви не будете обережні. Починаючи з ES5, це можна обійти, використовуючи map = Object.create(null), але це рідко робиться.
  • A Mapможе мати кращі результати у сценаріях, що передбачають часте додавання та видалення пар ключів.

MDN

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.