Когда использовать Карты вместо простых объектов JS

JavaScript ECMAScript 6

Автор: Дмитрий Павлютин

Переводчик: Front-end Xiaozhi

Источник: дмитрипавлутин

Ставьте лайк и смотрите снова, формируйте привычку

эта статьяGitHub GitHub.com/QQ449245884…Он был включен в вышеизложенное, и более ранние статьи с высокими похвалами были классифицированы, а также было систематизировано множество моих документов и учебных материалов. Добро пожаловать в Star and Perfect. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Надеюсь, у нас что-то получится вместе.

Простой объект JS{key: 'value'}Используется для хранения структурированных данных. Но есть одна вещь, которая меня раздражает: ключи объектов должны быть строками (или редко используемымиsymbol).

Что если цифры используются в качестве клавиш? В этом случае не будет ошибок:

const names = {
  1: 'One',
  2: 'Two',
};

Object.keys(names); // => ['1', '2']

JS неявно преобразует ключи объекта в строки, и это поведение по умолчанию теряет согласованность типов, и его сложно обойти. Но в ЕС6MapОбъекты могут помочь нам с такими проблемами, смотрите, смотрите, смотрите.

1. Карта принимает ключи любого типа

Как упоминалось ранее, если ключ объекта неstringилиsymbol, JS неявно преобразует его в строку.

К счастью,mapПроблем с типом ключа нет.

const numbersMap = new Map();

numbersMap.set(1, 'one');
numbersMap.set(2, 'two');

[...numbersMap.keys()]; // => [1, 2]

1а также2даnumbersMapключей в , тип (количество) этих ключей остается прежним.

допустимыйmpaИспользуйте любой тип ключа: числовой, логический, строковый иsymbol.

const booleansMap = new Map();

booleansMap.set(true, "Yep");
booleansMap.set(false, "Nope");

[...booleansMap.keys()]; // => [true, false]

booleansMapиспользоватьbooleansКак ключ без проблем. И наоборот, логические ключи не действуют на обычные объекты.

Прорвемся через воображение: использовать ли весь объект какmapключ, ответ: да.

1.1 Объекты как ключи

Предположим, вам нужно сохранить некоторые данные, связанные с объектом, не прикрепляя эти данные к самому объекту. Это невозможно с обычными объектами.

Обходной путь заключается в использовании массива кортежей объект-значение:

const foo = { name: 'foo' };
const bar = { name: 'bar' };

const kindOfMap = [
  [foo, 'Foo related data'],
  [bar, 'Bar related data']
]

kindOfMapпредставляет собой массив, содержащий пары объектов и связанных значений.

Самая большая проблема при таком подходе — сложность доступа к значениям по ключуO(n), мы должны перебрать весь массив, чтобы получить нужное значение по ключу.

function getByKey(kindOfMap, key) {
  for (const [k, v] of kindOfMap) {
    if (key === k) {
      return v;
    }
  }
  return undefined;
}

getByKey(kindOfMap, foo); // => 'Foo related data'

WeakMap(специализированная версия Map) может сделать это без особых проблем:он принимает объекты только как ключи.

Mapа такжеWeakmapОсновное различие между ними заключается в том,WeakmapПозволяет ключевым объектам собирать мусор, предотвращая утечки памяти.

Хорошо, используйтеWeakMapРефакторинг приведенного выше кода становится очень простым:

const foo = { name: 'foo' };
const bar = { name: 'bar' };

const mapOfObjects = new WeakMap();

mapOfObjects.set(foo, 'Foo related data');
mapOfObjects.set(bar, 'Bar related data');

mapOfObjects.get(foo); // => 'Foo related data'

а такжеMapНапротив,WeakMapпринимает только объекты в качестве ключей,и отсутствуют некоторые методы.

2. карта не имеет ограничений на имена ключей

Любой объект в JS наследует свойства объекта-прототипа, как и обычные объекты.

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

function isPlainObject(value) {
  return value.toString() === '[object Object]';
}

const actor = {
  name: 'Harrison Ford',
  toString: 'Actor: Harrison Ford'
};

// Does not work!
isPlainObject(actor); // TypeError: value.toString is not a function

Свойства, определенные для акторов объектовtoStringПереопределить, унаследованное от прототипаtoString()метод. это ломаетisObject(), потому что это зависит отtoString()метод.

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

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

Было бы удобно хранить состояние пользовательского поля в обычном объекте:

const userCustomFields = {
  'color':    'blue',
  'size':     'medium',
  'toString': 'A blue box'
};

Но пользователь может выбрать пользовательское имя поля, какtoString(как в примере), конструкторы и т. д., которые могут уничтожить наши объекты.

Не используйте введенные пользователем значения в качестве ключей для обычных объектов.

mapБез этой проблемы имена ключ-значение не ограничены:

function isMap(value) {
  return value.toString() === '[object Map]';
}

const actorMap = new Map();

actorMap.set('name', 'Harrison Ford');
actorMap.set('toString', 'Actor: Harrison Ford');

// Works!
isMap(actorMap); // => true

Независимо от тогоactorMapEстьtoStringхарактеристики,toString()методы все работают нормально.

3. карта повторяема

Для обхода свойств обычных объектов необходимо использовать другие вспомогательные статические функции, такие какObject.keys()илиObject.entries():

const colorsHex = {
  'white': '#FFFFFF',
  'black': '#000000'
};

for (const [color, hex] of Object.entries(colorsHex)) {
  console.log(color, hex);
}
// 'white' '#FFFFFF'
// 'black' '#000000'

Object.entries(colorsHex)Возвращает массив пар ключ-значение, извлеченный из объекта.

но,mapИтерируемый сам по себе:

const colorsHexMap = new Map();

colorsHexMap.set('white', '#FFFFFF');
colorsHexMap.set('black', '#000000');

for (const [color, hex] of colorsHexMap) {
  console.log(color, hex);
}
// 'white' '#FFFFFF'
// 'black' '#000000'

colorsHexMapявляется итерируемым. Его можно использовать везде, где допустима итерация:for()цикл, оператор спреда[...map].

mapПредоставляются методы, которые возвращают итерации:map.keys()перебирать ключи,map.values()перебирать значения

4. Размер карты

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

const exams = {
  'John Smith': '10 points',
  'Jane Doe': '8 points',
};

Object.keys(exams).length; // => 2

чтобы быть увереннымexamsразмера, необходимо передать все ключи, чтобы определить их количество.

map предоставляет свойство размера, которое представляет количество свойств.

const examsMap = new Map([
  ['John Smith', '10 points'],
  ['Jane Doe', '8 points'],
]);
  
examsMap.size; // => 2

КонечноmapКоличество свойств еще проще:examsMap.size.

Суммировать

Простые JS-объекты, как правило, хорошо хранят структурированные данные, но они также имеют некоторые ограничения:

  1. В качестве ключей можно использовать только строки или символы.
  2. собственные свойства объекта могут конфликтовать с ключами свойств, унаследованными от прототипа (например,toString,constructorЖдать).
  3. Объект нельзя использовать в качестве ключа

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

Не делайтеmapКак замену нормальному объекту, его следует рассматривать как дополнение к обычному объекту.

ты тоже знаешьmapЕсть ли другие преимущества перед обычными объектами?Оставьте комментарий ниже.


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

оригинал:Рисовое путешествие avlutin.com/maps-vs-para…

общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.