В главе Сборка мусора было отмечено, что движок JavaScript может хранить значение в памяти, если оно достижимо.
Вот пример:
Как правило, свойства или элементы таких структур данных, как объект или массив достижимы и хранятся в памяти, если эта структура данных находится в памяти. Например, после помещения объекта в массив он будет существовать до тех пор, пока существует массив.
Вот пример:
Соответственно, если применить объект в качестве ключа в обычной Map, он будет существовать до тех пор, пока существует карта.
Пример будет выглядеть так:
Далее мы рассмотрим WeakMap, который совершенно отличается и не удерживает объекты ключей от сборки мусора.
WeakMap
Основное отличие между Map и WeakMap состоит в том, что ключом WeakMap не могут быть примитивные значения. Они должны быть объектами, как в примере ниже:
Итерация и методы keys(), values(), entries() не поддерживаются WeakMap.
Методы, поддерживаемые WeakMap следующие: weakMap.get(key), weakMap.set(key, value), weakMap.has(key), и weakMap.delete(key).
weakMap.delete(key)
Основная область применения WeakMap - дополнительное хранение данных. WeakMap особенно полезен для хранения данных, связанных с сторонней библиотекой. Например, рассмотрим помещение данных в WeakMap, где объект является ключом. Как только объект собирается как мусор, данные также автоматически исчезают, как показано ниже:
let weakMap = new WeakMap();
let obj = {
name: "test"
};
key = weakMap.set(obj, "test docs");
// if obj disappears, test docs will be automatically destroyed
Теперь представьте, что у вас есть код, который поддерживает подсчет количества посещений для пользователей. Информация хранится внутри карты, где объект пользователя является ключом, а количество посещений - значением.
После ухода пользователя вы намерены прекратить хранение информации о его посещениях.
Сначала давайте рассмотрим пример функции подсчета с Map. Она будет выглядеть так:
Таким образом, при удалении пользователей необходимо очистить visitsCountMap. В противном случае, она будет храниться в памяти бесконечно.
Однако иногда такая очистка может стать неприятной задачей. Если вы хотите этого избежать, вы можете обратиться к WeakMap. Вот пример использования WeakMap вместо такой очистки:
Теперь нет необходимости очищать visitsCountMap.
О кэшировании
Кэширование происходит, когда результат функции должен быть запомнен (закэширован) для повторного использования при вызове на том же объекте.
Map может быть использован для хранения результатов следующим образом:
В случае вызова process(obj) с тем же объектом несколько раз, он вычислит результат только в первый раз. Позже он будет брать информацию из кэша.
Единственным недостатком кэширования является необходимость очистки кэша, как только вы больше не нуждаетесь в объекте.
Замена Map на WeakMap решит проблему. Закешированная информация будет автоматически удалена из памяти, как только объект будет собран как мусор.
Для большей точности рассмотрим пример ниже:
// cache.js
let cache = new WeakMap();
// calculate and remember the result
function process(obj) {
if (!cache.has(obj)) {
let res = /* calculate the result for */ obj;
cache.set(obj, res);
}
return cache.get(obj);
}
// main.js
let obj = { /* some object */ };
let res1 = process(obj);
let res2 = process(obj);
// later, when object is no longer needed:
obj = null;
// Can not get cache.size because it is WeakMap,
// but it is 0 or soon will be 0
//Once object gets garbage collected, the cached data will also be cleaned
WeakSet
WeakSet считается эквивалентом Set. Однако в WeakSet могут быть добавлены только объекты, а не примитивы.
Объект находится в наборе, пока он достижим в другом месте.WeakSet также поддерживает has, add и delete. Но не поддерживает итерации или size и keys().
Он также может служить дополнительным хранилищем для данных, но не для произвольных данных. Вот как выглядит пример добавления языков в WeakSet для отслеживания тех, на которых создан сайт:
У WeakMap и WeakSet есть серьезное ограничение: они не поддерживают итерации. Также нет возможности получить все текущее содержимое.
Сводка
В этой главе мы рассмотрели WeakMap и WeakSet.
В качестве итога можно сказать, что WeakMap считается коллекцией вроде Map, позволяя только объектам быть ключами. Он удаляет их вместе с связанным значением, когда они становятся недостижимыми.
WeakSet считается коллекцией, похожей на Set, которая хранит только объекты и удаляет их, когда они становятся недостижимыми.
Обе коллекции не поддерживают свойств и методов, не относящихся ко всем ключам или их количеству. Они позволяют только индивидуальные операции.
Время Викторины: Проверьте Свои Навыки!
отовы проверить свои знания? Погрузитесь в наши интерактивные викторины для более глубокого понимания и веселого способа закрепить знания.