WeakSet

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

Описание

Значения в WeakSet должны поддерживать сборку мусора. Большинство примитивных типов данных могут не иметь времени жизни, поэтому они не могут быть сохранены. Объекты и незарегистрированные символы могут быть сохранены потому что они поддерживают сборку мусора.

Ключевые отличия от Set:

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

    Примечание: Это также означает, что нет списка текущих значений сохранённых в наборе. Объекты WeakSet не перечислимы.

Вариант использования: обнаружение циклических ссылок

Функциям, которые вызывают себя рекурсивно, необходим способ защиты от циклических структур данных путём отслеживания того, какие объекты уже были обработаны.

Объекты WeakSet идеально подходят для этого:

js
// Выполняем `fn` для всего, что хранится внутри объекта.
function execRecursively(fn, subject, _refs = new WeakSet()) {
  // Избегаем бесконечно рекурсии
  if (_refs.has(subject)) {
    return;
  }

  fn(subject);
  if (typeof subject === "object" && subject) {
    _refs.add(subject);
    for (const key in subject) {
      execRecursively(fn, subject[key], _refs);
    }
    _refs.delete(subject);
  }
}

const foo = {
  foo: "Foo",
  bar: {
    bar: "Bar",
  },
};

foo.bar.baz = foo; // Циклическая ссылка!
execRecursively((obj) => console.log(obj), foo);

Здесь WeakSet создаётся при первом запуске и передаётся вместе с каждым последующим вызовом функции (с использованием внутреннего параметра _refs).

Количество объектов или порядок их обхода не имеют значения, поэтому использование WeakSet более эффективно, чем Set для ��тслеживания ссылок на объекты, особенно если задействовано очень большое количество объектов.

Конструктор

WeakSet()

Создаёт новый объект WeakSet.

Свойств экземпляра

Эти свойства определены в WeakSet.prototype и есть у всех экземпляров WeakSet.

WeakSet.prototype.constructor

Функция-конструктор, создающая экземпляр объекта. Для экземпляров WeakSet начальным значением является конструктор WeakSet.

WeakSet.prototype[@@toStringTag]

Начальным значением свойства @@toStringTag является строка "WeakSet". Это свойство используется в Object.prototype.toString().

Методы экземпляра

WeakSet.prototype.add()

Добавляет value в объект WeakSet.

WeakSet.prototype.delete()

Удаляет value из WeakSet. После этого WeakSet.prototype.has(value) будет возвращать false.

WeakSet.prototype.has()

Возвращает булево значение, показывающее присутствует ли value в объекте WeakSet или нет.

Примеры

Использование WeakSet

js
const ws = new WeakSet();
const foo = {};
const bar = {};

ws.add(foo);
ws.add(bar);

ws.has(foo); // true
ws.has(bar); // true

ws.delete(foo); // удаляем foo из набора
ws.has(foo); // false, foo был удалён
ws.has(bar); // true, bar сохранился

Обратите внимание, что foo !== bar. Хотя это похожие объекты, это не один и тот же объект. И поэтому они оба добавляются в набор.

Спецификации

Specification
ECMAScript Language Specification
# sec-weakset-objects

Совместимость с браузерами

BCD tables only load in the browser

Смотрите также