Карты против объектов в 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, ты можешь придумать, когда я должен это сделать, хотя :( Сложно думать о вариантах использования.
Мэтью Харвуд,
7
Вы можете использовать его там, где вы говорите элемент DOM, с которым вы хотите связать некоторые данные с помощью объекта. Вместо использования, скажем, идентификатора элемента в качестве ключа в объекте, вы можете использовать сам элемент в качестве ключа на карте, поэтому вам все равно, имеет ли элемент идентификатор (или любой другой уникальный идентификатор, кроме ссылки на объект. ) или нет.
RobG
1
@RobG просто небольшое дополнение: в этом случае оно также WeakMapможет быть полезно.
zerkms
1
Я думаю, это предлагает использовать объекты как / для записей и Maps для всех других видов сопоставления. Под записями я подразумеваю структуру данных с фиксированным набором полей, такую ​​как пользовательский объект, который имеет поля nameи, idнапример.
Феликс Клинг,
1
Когда я читал эту страницу MDN, маркированный список вариантов использования был намного полезнее, чем процитированный вами абзац. Конечно, в отношении вопроса, поставленного в вашем заголовке.
CodingIntrigue

Ответы:

51

Каков применимый пример использования карт поверх объектов?

Я думаю, вы уже привели один хороший пример: вам, по крайней мере, нужно использовать Maps, когда вы используете объекты (включая объекты Function) в качестве ключей.

в частности, «когда ключи будут неизвестны до времени выполнения?»

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

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

Берги
источник
1
Или с другой точки зрения: всякий раз, когда вам нужно перебрать свойства вашего объекта на уровне данных (например for..of), а не на уровне программы (например for..in), используйте 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 и не пытаться давать советы по программированию.
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"}
слайдшоуp2
источник
3

Objects похожи на Maps в том, что оба позволяют вам устанавливать ключи для значений, извлекать эти значения, удалять ключи и определять, хранится ли что-то в ключе. Из-за этого (и из-за отсутствия встроенных альтернатив) s исторически Objectиспользовались как Maps; однако есть важные отличия, которые делают использование Mapв определенных случаях предпочтительным:

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

MDN

codejockie
источник
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

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

Удачи в оценке итератора карт

Объекты можно оценивать любой IDE:

WebStorm оценивает объект

Дэн Даскалеску
источник
7
Это вообще не отвечает на вопрос « Каков применимый пример использования карт поверх объектов? »
Берги
6
Пожалуйста, не публикуйте свои ответы. И нет, вопрос не дубликат.
Берги