WeakSet

Baseline 廣泛可用 *

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 2015 年 9 月以來,該特性已在各大瀏覽器中可用。

* 此特性的某些部分可能存在不同級別的支援。

WeakSet 是一種可垃圾回收的值的集合,包括物件和未註冊的 SymbolWeakSet 中的值只能出現一次。在 WeakSet 的集合中是唯一的。

描述

WeakSet 的值必須是可垃圾回收的。大多數原始資料型別可以任意建立且沒有生命週期,因此不能儲存。物件和未註冊的 Symbol 可以儲存,因為它們是可垃圾回收的。

Set 物件的主要區別在於

  • WeakSet 僅包含物件和 Symbol。它們不能包含任意型別的值,而Set 可以。

  • WeakSet的,這意味著對 WeakSet 中物件的引用是弱引用。如果 WeakSet 中儲存的值沒有其他引用存在,這些值就可以被垃圾回收。

    注意:這也意味著集合中沒有儲存當前值的列表。WeakSet 是不可列舉的。

鍵的相等性

與常規 Set 一樣,值相等性基於SameValueZero 演算法,該演算法與 === 運算子相同,因為 WeakSet 只能包含物件和 Symbol 值。這意味著對於物件值,相等性基於物件標識。它們是透過引用而不是值進行比較的。

建構函式

WeakSet()

建立一個新的 WeakSet 物件。

例項屬性

這些屬性定義在 WeakSet.prototype 上,並由所有 WeakSet 例項共享。

WeakSet.prototype.constructor

建立例項物件的建構函式。對於 WeakSet 例項,初始值為 WeakSet 建構函式。

WeakSet.prototype[Symbol.toStringTag]

[Symbol.toStringTag] 屬性的初始值為字串 "WeakSet"。此屬性用於 Object.prototype.toString()

例項方法

WeakSet.prototype.add()

將指定值插入此集合,如果尚不存在。

WeakSet.prototype.delete()

如果指定值存在於此集合中,則將其從集合中移除。

WeakSet.prototype.has()

返回一個布林值,指示指定值是否存在於此 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); // removes foo from the set
ws.has(foo); // false, foo has been removed
ws.has(bar); // true, bar is retained

請注意,foo !== bar。雖然它們是相似的物件,但它們不是同一個物件。因此它們都被新增到了集合中。

檢測迴圈引用

遞迴呼叫的函式需要一種方法來防止迴圈資料結構,透過跟蹤哪些物件已經被處理。

WeakSet 非常適合此目的

js
// 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 引數)傳遞。

物件的數量或它們的遍歷順序並不重要,因此 WeakSetSet 更適合(且效能更好)來跟蹤物件引用,尤其是當涉及大量物件時。

規範

規範
ECMAScript® 2026 語言規範
# sec-weakset-objects

瀏覽器相容性

另見