Кратко
WeakMap и WeakSet — коллекции, хранящие слабые ссылки на объекты. Если объект удалён из обычных ссылок — сборщик мусора удалит его и из WeakMap/WeakSet. Нельзя перечислить содержимое, узнать размер. Используются для приватных данных и кэширования.
Подробно
Map/Set vs WeakMap/WeakSet:
Map:
- Ключи: любые значения (включая примитивы)
- Перечисление: keys(), values(), entries(), size
- Ссылки: сильные (объекты не удаляются, пока есть Map)
WeakMap:
- Ключи: ТОЛЬКО объекты
- Перечисление: НЕТ
- Ссылки: слабые (объект может быть удалён GC)
- Методы: get, set, has, delete
WeakSet:
- Значения: ТОЛЬКО объекты
- Перечисление: НЕТ
- Методы: add, has, delete
Зачем нужны слабые ссылки:
// Кэширование результатов для объектов const cache = new WeakMap();
function process(obj) { if (cache.has(obj)) { return cache.get(obj); } const result = expensiveCalculation(obj); cache.set(obj, result); return result; }
// Когда объект удалён — кэш тоже очищается автоматически
// Приватные данные класса const privateData = new WeakMap();
class User { constructor(name) { privateData.set(this, { name }); } getName() { return privateData.get(this).name; } }
// Когда экземпляр User удалён — данные тоже удаляются
Ментальная модель
WeakMap — как шкаф с ячейками для пальто. Вы кладёте пальто (объект) в ячейку (ключ). Когда пальто убирают из гардероба (GC) — ячейка автоматически очищается. Но вы не можете посмотреть, сколько пальто в шкафу (нет перечисления).
Примеры
**Самый простой:**
const weakMap = new WeakMap();
let obj = { name: 'test' };
weakMap.set(obj, 'данные');
console.log(weakMap.has(obj)); // true
obj = null; // объект может быть собран GC
// weakMap автоматически очиститсяWeakMap: ключи — объекты, ссылки — слабые.
**Простой:**
// Приватные данные
class User {
constructor(name, age) {
this.name = name;
privateData.set(this, { age });
}
getAge() {
return privateData.get(this).age;
}
}
const privateData = new WeakMap();
const user = new User('Анна', 25);
console.log(user.getAge()); // 25
// user.age — undefined (приватно)WeakMap для приватных данных класса.
**Реальный пример:**
// Кэширование DOM-элементов
class ComponentCache {
constructor() {
this.cache = new WeakMap();
}
getRenderResult(element) {
if (this.cache.has(element)) {
return this.cache.get(element);
}
const result = this.render(element);
this.cache.set(element, result);
return result;
}
render(element) {
return `Rendered: ${element.tagName}`;
}
}
// Когда DOM-элемент удалён из страницы — кэш очищаетсяРеальный пример: кэш результатов рендеринга DOM-элементов.
Частые ошибки
**Неправильно:** Думать, что WeakMap — это Map с меньшим API
**Почему:** WeakMap хранит слабые ссылки — объект может быть удалён GC. Map хранит сильные ссылки.
**Правильно:** WeakMap = слабые ссылки + автоматическая очистка. Map = сильные ссылки + ручная очистка.
**Неправильно:** Пытаться перечислить WeakMap
**Почему:** WeakMap не имеет методов keys(), values(), entries(), size.
**Правильно:** WeakMap нельзя перечислить — это ограничение по спецификации.
Важно запомнить
- WeakMap/WeakSet хранят только объекты
- Ссылки слабые — GC может удалить объект
- Нельзя перечислить содержимое
- Используйте для кэширования и приватных данных
- WeakRef (JV20) — ещё более низкоуровневый механизм
Связь
Назад: Вы знаете Map и Set (JI18). WeakMap/WeakSet — их варианты со слабыми ссылками.
Вперёд: Следующий урок (JV6) — внутреннее устройство цепочки прототипов.