WeakMap и WeakSet
WeakSet – особый вид Set не препятствующий сборщику мусора удалять свои элементы. То же самое – WeakMap для Map . То есть, если некий объект присутствует только в WeakSet/WeakMap – он удаляется из памяти.
Это нужно для тех ситуаций, когда основное место для хранения и использования объектов находится где‑то в другом месте кода, а здесь мы хотим хранить для них «вспомогательные» данные, существующие лишь пока жив объект.
Например, у нас есть элементы на странице или, к примеру, пользователи, и мы хотим хранить для них вспомогательную информацию, например обработчики событий или просто данные, но действительные лишь пока объект, к которому они относятся, существует.
Если поместить такие данные в WeakMap , а объект сделать ключом, то они будут автоматически удалены из памяти, когда удалится элемент. Например:
// текущие активные пользователи let activeUsers = [
{name: "Вася"},
{name: "Петя"},
{name: "Маша"}
];
// вспомогательная информация о них,
// которая напрямую не входит в объект юзера,
// и потому хранится отдельно let weakMap = new WeakMap();
weakMap[activeUsers[0]] = 1;
weakMap[activeUsers[1]] = 2;
weakMap[activeUsers[2]] = 3;
alert( weakMap[activeUsers[0]] ); // 1
activeUsers.splice(0, 1); // Вася более не активный пользователь
// weakMap теперь содержит только 2 элемента activeUsers.splice(0, 1); // Петя более не активный пользователь
// weakMap теперь содержит только 1 элемент
Таким образом, WeakMap избавляет нас от необходимости вручную удалять вспомогательные данные, когда удалён основной объект. У WeakMap есть ряд ограничений:
Нет свойства size .
Нельзя перебрать элементы итератором или forEach .
Нет метода clear() .
Иными словами, WeakMap работает только на запись ( set , delete ) и чтение ( get , has ) элементов по конкретному ключу, а не как полноценная коллекция. Нельзя вывести всё содержимое WeakMap , нет соответствующих методов.
Это связано с тем, что содержимое WeakMap может быть модифицировано сборщиком мусора в любой момент, независимо от программиста. Сборщик мусора работает сам по себе. Он не гарантирует, что очистит объект сразу же, когда это стало возможным. В равной степени он не гарантирует и обратное. Нет какого‑то конкретного момента, когда такая очистка точно произойдёт – это определяется внутренними алгоритмами сборщика и его сведениями о системе.
Поэтому содержимое WeakMap в произвольный момент, строго говоря, не определено. Может быть, сборщик мусора уже удалил какие‑то записи, а может и нет. С этим, а также с требованиями к эффективной реализации WeakMap , и связано отсутствие методов, осуществляющих доступ ко всем записям.
То же самое относится и к WeakSet : можно добавлять элементы, проверять их наличие, но нельзя получить их список и даже узнать количество.
Эти ограничения могут показаться неудобными, но по сути они не мешают WeakMap/WeakSet выполнять свою основную задачу – быть «вторичным» хранилищем данных для объектов, актуальный список которых (и сами они) хранятся в каком‑то другом месте.
Итого
Map – коллекция записей вида ключ: значение , лучше Object тем, что перебирает всегда в порядке вставки и допускает любые ключи.
Set – коллекция уникальных элементов, также допускает любые ключи.
Основная область применения Map – ситуации, когда строковых ключей не хватает (нужно хранить соответствия для ключей‑объектов), либо когда строковый ключ может быть совершенно произвольным.
К примеру, в обычном объекте Object нельзя использовать «совершенно любые» ключи. Есть встроенные методы, и уж точно есть свойство с названием proto , которое зарезервировано системой. Если название ключа даётся посетителем сайта, то он может попытаться использовать такое свойство, заменить прототип, а это, при запуске JavaScript на сервере, уже может привести к серьёзным ошибкам.
WeakMap и WeakSet – «урезанные» по функционалу варианты Map/Set , которые позволяют только «точечно» обращаться элементам (по конкретному ключу или значению). Они не препятствуют сборке мусора, то есть если ссылка на объект осталась только в WeakSet/WeakMap – он будет удалён.
Do'stlaringiz bilan baham: |