WeakSet
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015.
WeakSet
— это набор значений, поддерживающих сборку мусора, включая объекты и незарегистрированные символы. Каждое значение в WeakSet
может встречаться только один раз, оно уникально в коллекции WeakSet
.
Описание
Значения в WeakSet должны поддерживать сборку мусора. Большинство примитивных типов данных могут не иметь времени жизни, поэтому они не могут быть сохранены. Объекты и незарегистрированные символы могут быть сохранены потому что они поддерживают сборку мусора.
Ключевые отличия от Set
:
-
WeakSet
— это набор только объектов и символов. В отличие отSet
он не может содержать произвольные значения любого типа. -
WeakSet
является слабым в том смысле, что ссылки на объекты вWeakSet
хранятся слабо. Если нет других ссылок на значение, хранящееся вWeakSet
, эти значения могут быть удалены сборщиком мусора.Примечание: Это также означает, что нет списка текущих значений сохранённых в наборе. Объекты
WeakSet
не перечислимы.
Вариант использования: обнаружение циклических ссылок
Функциям, которые вызывают себя рекурсивно, необходим способ защиты от циклических структур данных путём отслеживания того, какие объекты уже были обработаны.
Объекты WeakSet
идеально подходят для этого:
// Выполняем `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
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