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.
WeakSets
are 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
非常适合此目的:
¥WeakSet
s 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