JS Advanced

WeakMap и WeakSet

Понять разницу между Map/Set и WeakMap/WeakSet: слабые ссылки, сборка мусора, и почему перечисление содержимого невозможно.

Продвинутый (Advanced)
Нужно знать:Map и SetОбъекты

Кратко

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) — ячейка автоматически очищается. Но вы не можете посмотреть, сколько пальто в шкафу (нет перечисления).


Примеры

**Самый простой:**

javascript
const weakMap = new WeakMap();
let obj = { name: 'test' };

weakMap.set(obj, 'данные');
console.log(weakMap.has(obj)); // true

obj = null; // объект может быть собран GC
// weakMap автоматически очистится

WeakMap: ключи — объекты, ссылки — слабые.

**Простой:**

javascript
// Приватные данные
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 для приватных данных класса.

**Реальный пример:**

javascript
// Кэширование 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) — внутреннее устройство цепочки прототипов.

Материалы курса JS Advanced — PROlab Academy.