> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b5-collections/03-weak-collections.md).

# 03. Weak Collections

Коллекции со слабыми ссылками (*weak references*) отличаются стратегией хранения объектов: если некий объект присутствует только в коллекции со слабыми ссылками, то сборщику мусора разрешается очищать из памяти данный объект. Ключами таких коллекций обязаны быть объекты, а значениями -- произвольные значения.

Классы `WeakSet/WeakMap` полезны для ситуаций в которых вы ассоциируете данные с объектами, чей жизненный цикл вы не собираетесь контролировать:

* Кэширование промежуточных результатов
* Сохранение временных приватных данных

## `WeakMap`

`WeakMap` - это карта со слабыми ключами. `WeakMap` избавляет нас от необходимости вручную удалять вспомогательные данные (значения карты), когда удалён основной объект.

```javascript
const wm = new WeakMap();

wm.set("abc", 123); // TypeError
wm.set({}, 123); // OK
```

У `WeakMap` есть ряд ограничений:

* Ключами обязаны быть только объекты
* Нет свойства `size`.
* Нельзя узнать содержимое карты
* Нельзя перебрать элементы итератором или `forEach`.
* Нет метода `clear()`.
* Не является итерируемыми

`WeakMap` работает только на запись (`set`, `delete`) и чтение (`get`, `has`) элементов по конкретному ключу, а не как полноценная коллекция. Нельзя вывести всё содержимое `WeakMap`, нет соответствующих методов.

Содержимое `WeakMap` в произвольный момент, строго говоря, не определено. Может быть, сборщик мусора уже удалил какие-то записи, а может и нет. С этим, а также с требованиями к эффективной реализации `WeakMap`, и связано отсутствие методов, осуществляющих доступ ко всем записям. Содержимое `WeakMap` может быть модифицировано сборщиком мусора в любой момент, независимо от программиста. Сборщик мусора работает сам по себе. Он не гарантирует, что очистит объект сразу же, когда это стало возможным. В равной степени он не гарантирует и обратное. Нет какого-то конкретного момента, когда такая очистка точно произойдёт — это определяется внутренними алгоритмами сборщика и его сведениями о системе.

Пример:

```javascript
const cache = new WeakMap();
function countOwnKeys(obj) {
  if (cache.has(obj)) {
    console.log("Cached");
    return cache.get(obj);
  } else {
    console.log("Computed");
    const count = Object.keys(obj).length;
    cache.set(obj, count);
    return count;
  }
}
```

## `WeakSet`

`WeakSet` — особый вид `Set` не препятствующий сборщику мусора удалять свои элементы. Все ограничения, накладываемые на `WeakMap`, так же справедливы и для `WeakSet`. Можно добавлять элементы в `WeakSet`, проверять их наличие, но нельзя получить их список и даже узнать количество.

Example: class `Foo` can ensure that its methods are only applied to instances that were created by it:

```javascript
const foos = new WeakSet();

class Foo {
  constructor() {
    foos.add(this);
  }

  method() {
    if (!foos.has(this)) {
      throw new TypeError("Incompatible object!");
    }
  }
}
```
