Допустим, у нас есть какой-то объект с данными:
Код
let user = {name: 'Ivan'};
И на каком-то этапе
user примет значение
null Если мы сейчас выведем в консоль содержимое
user, то получим
null, объект в памяти больше не существует, на него нет никаких ссылок.
Но, если в наш код мы добавим массив, в котором будет лежать ссылка на объект
user, далее также присвоим для
user значение
null и выведем в консоль
user и первый элемент массива
arr Код
let user = {name: 'Ivan'};
const arr = [user];
user = null;
console.log(user); // null
console.log(arr[0]); // { name: 'Ivan' }
Как мы видим, объект все еще хранится в памяти, так как в консоль вывелись данные из этого объекта. Пока ссылка на объект существует, он будет храниться в памяти.
По аналогии будет с картой (
Map), пока карта существует, объект будет храниться в памяти.
Код
let user = {name: 'Ivan'};
let map = new Map();
map.set(user, 'data');
user = null;
console.log(map.keys());
Цитата
[Map Iterator] { { name: 'Ivan' } }
Опять мы видим, что хоть мы и удалили объект через присвоение ему значения
null (строка 7), за счет того, что в карте осталась ссылка на этот объект (строка 5), он будет продолжать храниться в памяти.
WeakMap - или "слабая карта" а) ключами в ней могут быть только объекты
б) если нет ссылки на объект, который существует только внутри
WeakMap, он будет удалён из этой карты
Код
let user = {name: 'Ivan'};
let map = new WeakMap(); // создали слабую карту
map.set(user, 'data');
user = null;
console.log(map.has(user)); // false
Для
WeakMap доступны лишь методы
set(), get(), delete(), has() Для использования
WeakMap нужны определённые условия, например, временное хранилище объектов в работе сайта или приложения или кэшировании данных.
Допустим, у нас есть чат, в котором сидят десятки людей и нам нужно всех их хранить для отображения. При этом, кто-то входит в онлайн, кто-то выходит и это нужно отслеживать.
Создадим новую карту WeakMap, изначально пустую, а также функцию, которая будет кэшировать(запоминать) каждого нового пользователя, который вошел в чат и запоминать его в карте, если же пользователь покидает чат, то он удаляется из карты.
Код
let cashe = new WeakMap();
function casheUser(user) {
if (!cashe.has(user)) {
cashe.set(user, Date.now());
}
return cashe.get(user);
}
Создадим нескольких пользователей:
Код
let lena = {name: 'Elena'};
let alex = {name: 'Alex'};
Допустим, оба этих пользователя вошли в чат:
Код
// пользователи вошли в чат
casheUser(lena);
casheUser(alex);
В какой-то момент времени Елена вышла из чата:
Получается, объект
lena удалён (
null), а так как ссылка на его была только внутри
WeakMap, то и в памяти он будет очищен.
Проверим это, выведем в консоль результат проверки, есть ли такой объект
lena в
WeakMap Код
console.log(cashe.has(lena)); // false
console.log(cashe.has(alex)); // true
WeakSet - данная коллекция аналогична обычному
Set, но в
WeakSeat можно добавлять только объекты.
WeakSet поддерживает методы
add(), has() и
delete(), метод
get() не поддерживается.
Разбираем на примере сообщений в чате.
Допустим, у нас есть массив с объектами, в котором будут сообщения и информация от кого эти сообщения:
Код
let messages = [
{ text: "Hello", from: "John" },
{ text: "World", from: "Alex" },
{ text: "....", from: "M" }
];
Далее создадим новую структуру данных, содержащую уже прочитанные сообщения:
Код
let readMessages = new WeakSet();
При прочтении сообщений они добавляются в наш
WeakSet Код
// Прочитанные сообщения добавляются в наш набор
readMessages.add(messages[0]);
readMessages.add(messages[1]);
Проверим, есть ли в нашем наборе, к примеру, первое сообщение:
Код
console.log(readMessages.has(messages[0])); // true
Если сейчас удалить из нашего массива первый объект, то ссылка на него останется только внутри
WeakSet, поэтому он даст команду сборщику мусора удалить этот объект
Код
let messages = [
{ text: "Hello", from: "John" },
{ text: "World", from: "Alex" },
{ text: "....", from: "M" }
];
let readMessages = new WeakSet();
// Прочитанные сообщения добавляются в наш набор
readMessages.add(messages[0]);
messages.shift(); // удаляем первый элемент массива
// Проверяем, есть ли такой элемент в наборе
console.log(readMessages.has(messages[0])); // false
Всего комментариев: 0