Узнайте, что такое WeakMap, варианты его использования, чем он отличается от Map и когда вам следует использовать Map & WeakMap в JavaScript.

JavaScript предоставляет множество встроенных объектов, которые помогают сделать жизнь разработчиков JavaScript легкой и безболезненной. Некоторые из этих хорошо известных объектов, но не ограничиваются ими:

  • Множество
  • Дата
  • JSON
  • карта
  • Обещать

Однако в JavaScript также есть несколько малоизвестных встроенных объектов, которые при правильном использовании могут заметно повысить производительность приложения JavaScript.

Одним из таких объектов является WeakMap.

Что такое слабая карта?

Согласно MDN, WeakMap можно определить как набор пар ключ/значение, ключ которых должен быть объектами, со значениями любого произвольного «типа JavaScript и не создать сильную ссылку на его ключи»

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

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

Чем WeakMap отличается от карты?

WeakMap происходит от объекта Map, и хотя он очень похож по синтаксису, он также сильно отличается по-своему.

Отличия:

С объектом карты JavaScript:

  1. Вы можете установить ключ карты для любого типа JavaScript, такого как объекты и примитивы.
  2. Он создает сильную ссылку на свои ключи
  3. Позволяет использовать методы перечисления, такие как forEach(), keys(), values() и другие, для получения списка ключей и значений карты.

Что касается WeakMap:

  1. Ключ слабой карты ДОЛЖЕН относиться к объектному типу. Любые другие значения вызовут ошибку.
  2. Он НЕ создает сильную ссылку на свои ключи.
  3. Он не допускает перечисления, что означает, что вы не сможете использовать такие методы, как keys(), values() или entry() для получения списка ключей или значений.
  4. Разрешает сборку мусора любых значений, если на их ключевые объекты нет ссылок откуда-либо, кроме WeakMap.

Сходства:

И WeakMap, и Map поддерживают такие методы, как:

  • получать()
  • набор()
  • имеет()
  • удалить()

Как мы можем реализовать WeakMap?

Теперь, когда мы разобрались с теорией, давайте посмотрим, как легко реализовать объект WeakMap.

WeakMap можно создать, вызвав новый метод. Без него будет выдаваться ошибка.

const weakMap = new WeakMap();

Установка ключа и значения для WeakMap:

const user1 = {name: 'Kwadjo'} //Requires the key to be of an object
weakMap.set(user1, '22');

Возврат элемента из WeakMap так же прост, как вызов метода get().

console.log(weakMap.get(user1)) // Returns "22"

Вывоз мусора:

Как упоминалось ранее, основное различие между Map и WeakMap сводится к сборщику мусора.

Давайте быстро пробежимся по сборке мусора.

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

Учитывая следующий пример, где мы создаем объект:

let user2 = { name: "Afia" };

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

Если бы мы сейчас перезаписали ссылку на user2:

user2 = null;

Это пометит объект как сборщик мусора и удалит его из памяти.

Хм, а как это относится к Map и WeakMap?

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

let user3 = { name: "Obenewaa" };
let map = new Map();
map.set(user3, 'hello');

Если бы мы использовали карту console.log, мы бы получили:

console.log(map);
//Output: {{   "name": "Obenewaa" } => "hello"}

Напомним, ранее я упоминал, что Map создает сильную ссылку на свои ключи. Давайте проверим это, установив для пользователя user3 значение null и запротоколировав вывод в консоли:

user3 = null;
console.log(map);
//Output: {{   "name": "Obenewaa" } => "hello"}

Вы заметите, хотя мы перезаписали ссылку на user3, объект Map по-прежнему содержит сильную ссылку на объект. Таким образом, хотя вызов метода get() объекта Map вернет неопределенное значение, другие методы, такие как has() или forEach(), по-прежнему смогут вернуть объект.

Это связано с тем, что по мере того, как объект Map продолжает существовать, он будет существовать и не будет собираться мусором.

Давайте попробуем это на WeakMap:

let user3 = { name: "Obenewaa" };
let weakMap = new WeakMap();
weakMap.set(user3, 'hello');

Поскольку WeakMap не является перечислимым, нам придется использовать метод get() для вывода значения:

console.log(weakMap.get(user3)) // 'hello'

Если мы сейчас перезапишем user3 в null и попытаемся вывести значение, то получим undefined:

user3 = null;
console.log(weakMap.get(user3)); //returns undefined

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

Но подождите! Почему WeakMap не поддерживает методы Iterable?

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

Это означало бы, что WeakMap не будет знать своего количества или размера из-за того, что сборщик мусора мог очистить свои ключи или частично очистить некоторые из своих ключей.

Когда я должен использовать карту или WeakMap

Простой способ определить, когда использовать Map или WeakMap, можно определить следующим образом:

  • Если вы хотите иметь список ключей или требовать перечисления — используйте Карту.
  • Если вам нужно, чтобы ключи объектов удалялись и не хранились в памяти после того, как на них больше не ссылаются, используйте WeakMap.

Случаи использования WeakMap:

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

Вы использовали объект WeakMap или не знакомы с ним? Оставьте комментарий ниже о своих мыслях и примерах использования объекта WeakMap.

Если вам понравилась эта статья, ознакомьтесь с другими моими статьями ниже:

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.