WeakSet
WeakSet 是垃圾可回收值的集合,包括对象和 非注册符号。WeakSet 中的值只能出现一次。它在 WeakSet 系列中是独一无二的。
¥A WeakSet is a collection of garbage-collectable values, including objects and non-registered symbols. A value in the WeakSet may only occur once. It is unique in the WeakSet's collection.
描述
¥Description
WeakSet 的值必须是可垃圾回收的。大多数 primitive data types 可以任意创建并且没有生命周期,因此无法存储。对象和 非注册符号 可以被存储,因为它们是垃圾可收集的。
¥Values of WeakSets must be garbage-collectable. Most primitive data types can be arbitrarily created and don't have a lifetime, so they cannot be stored. Objects and non-registered symbols can be stored because they are garbage-collectable.
与 Set 对象的主要区别是:
¥The main differences to the Set object are:
WeakSet仅是对象和符号的集合。它们不能像Set那样包含任何类型的任意值。WeakSet是弱的,这意味着对WeakSet中对象的引用是弱保存的。如果不存在对存储在WeakSet中的值的其他引用,则可以对这些值进行垃圾收集。注意:这也意味着集合中没有存储当前值的列表。
WeakSets不可枚举。¥Note: This also means that there is no list of current values stored in the collection.
WeakSetsare not enumerable.
使用案例:检测循环引用
¥Use case: Detecting circular references
递归调用自身的函数需要一种通过跟踪哪些对象已被处理来防止循环数据结构的方法。
¥Functions that call themselves recursively need a way of guarding against circular data structures by tracking which objects have already been processed.
WeakSet 非常适合此目的:
¥WeakSets are ideal for this purpose:
// Execute a callback on everything stored inside an object
function execRecursively(fn, subject, _refs = new WeakSet()) {
// Avoid infinite recursion
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; // Circular reference!
execRecursively((obj) => console.log(obj), foo);
此处,WeakSet 在第一次运行时创建,并与每个后续函数调用一起传递(使用内部 _refs 参数)。
¥Here, a WeakSet is created on the first run, and passed along with every subsequent function call (using the internal _refs parameter).
对象的数量或其遍历顺序并不重要,因此 WeakSet 比 Set 更适合(且性能更高)来跟踪对象引用,特别是在涉及大量对象的情况下。
¥The number of objects or their traversal order is immaterial, so a WeakSet is more suitable (and performant) than a Set for tracking object references, especially if a very large number of objects is involved.
构造函数
实例属性
¥Instance properties
这些属性在 WeakSet.prototype 上定义并由所有 WeakSet 实例共享。
¥These properties are defined on WeakSet.prototype and shared by all WeakSet instances.
WeakSet.prototype.constructor-
创建实例对象的构造函数。对于
WeakSet实例,初始值为WeakSet构造函数。 WeakSet.prototype[Symbol.toStringTag]-
[Symbol.toStringTag]属性的初始值为字符串"WeakSet"。该属性在Object.prototype.toString()中使用。
实例方法
¥Instance methods
WeakSet.prototype.add()-
将
value附加到WeakSet对象。 WeakSet.prototype.delete()-
从
WeakSet中删除value。之后WeakSet.prototype.has(value)将返回false。 WeakSet.prototype.has()-
返回一个布尔值,断言
value是否存在于WeakSet对象中。
示例
使用 WeakSet 对象
¥Using the WeakSet object
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); // removes foo from the set
ws.has(foo); // false, foo has been removed
ws.has(bar); // true, bar is retained
请注意,foo !== bar。虽然它们是相似的对象,但它们不是同一个对象。因此它们都被添加到集合中。
¥Note that foo !== bar. While they are similar objects, they are not the same object. And so they are both added to the set.
规范
| Specification |
|---|
| ECMAScript Language Specification # sec-weakset-objects |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also