Перейти к содержимому

51. WeakSet и WeakMap

Иллюстрация к уроку WeakSet и WeakMap – это специальные типы коллекций в JavaScript, которые помогают оптимизировать использование памяти, особенно при работе с DOM и другими объектами. Они отличаются от обычных Set и Map тем, что не препятствуют сборщику мусора удалять объекты, на которые они ссылаются.

WeakSet – это коллекция, которая может хранить только объекты. В отличие от обычного Set, WeakSet не хранит сильные ссылки на объекты. Это значит, что если объект, находящийся в WeakSet, больше нигде не используется, сборщик мусора может его удалить, даже если он все еще находится в WeakSet. WeakSet полезен для хранения информации о том, какие объекты, например DOM-элементы, уже обработаны.

Пример:

let weakSet = new WeakSet();
let obj1 = {};
let obj2 = {};
weakSet.add(obj1);
weakSet.add(obj2);
console.log(weakSet.has(obj1)); // true
obj1 = null; // obj1 больше не используется
// В какой-то момент сборщик мусора удалит obj1 из WeakSet
// После этого weakSet.has(obj1) вернет false

Методы WeakSet:

  • add(object): Добавляет объект в WeakSet.
  • delete(object): Удаляет объект из WeakSet.
  • has(object): Проверяет, есть ли объект в WeakSet.

Важно: WeakSet не поддерживает итерацию (нельзя получить список элементов).

WeakMap – это коллекция, которая позволяет связывать объекты с произвольными данными. Как и WeakSet, WeakMap не хранит сильные ссылки на ключи (которые должны быть объектами). Если ключ WeakMap больше нигде не используется, сборщик мусора может его удалить, а вместе с ним и значение, связанное с этим ключом. WeakMap часто используется для хранения приватных данных объектов.

Пример:

let weakMap = new WeakMap();
let obj1 = {};
let obj2 = {};
weakMap.set(obj1, "Информация об obj1");
weakMap.set(obj2, "Информация об obj2");
console.log(weakMap.get(obj1)); // "Информация об obj1"
obj1 = null; // obj1 больше не используется
// В какой-то момент сборщик мусора удалит obj1 из WeakMap
// После этого weakMap.get(obj1) вернет undefined

Методы WeakMap:

  • set(object, value): Связывает объект с значением.
  • get(object): Возвращает значение, связанное с объектом.
  • delete(object): Удаляет связь между объектом и значением.
  • has(object): Проверяет, есть ли связь для объекта.

Важно: WeakMap не поддерживает итерацию (нельзя получить список ключей и значений).

// Используем WeakMap для хранения приватных данных объекта
let weakMap = new WeakMap();
class User {
constructor(name) {
weakMap.set(this, { name: name, isAdmin: false }); // Храним приватные данные
}
getName() {
return weakMap.get(this).name; // Получаем приватные данные
}
setAdmin() {
weakMap.get(this).isAdmin = true;
}
isAdmin() {
return weakMap.get(this).isAdmin;
}
}
let user = new User("Иван");
console.log(user.getName()); // Иван
user.setAdmin();
console.log(user.isAdmin()); // true

WeakSet и WeakMap часто используются во фреймворках и библиотеках для работы с DOM. Например, они могут применяться для хранения данных, связанных с DOM-элементами, без риска утечек памяти. Представьте себе систему обработки событий на веб-странице. Можно использовать WeakMap, чтобы связать каждый DOM-элемент с обработчиками событий, которые к нему привязаны. Когда элемент удаляется из DOM, сборщик мусора сможет его удалить, и связанные с ним обработчики событий будут автоматически освобождены. Это предотвращает “висячие” обработчики и утечки памяти.

  • WeakSet и WeakMap хранят только объекты в качестве ключей (WeakSet) или ключей для значений (WeakMap).
  • Они не препятствуют сборщику мусора удалять объекты, на которые они ссылаются.
  • Не поддерживают итерацию.
  • Используются для оптимизации памяти и хранения приватных данных.
  • Полезны при работе с DOM и другими объектами, время жизни которых контролируется не кодом, который их использует.