WeakRef
Baseline 廣泛可用 *
WeakRef 物件允許您持有對另一個物件的弱引用,而不會阻止該物件被垃圾回收。
描述
WeakRef 物件包含一個對物件的弱引用,該物件被稱為其目標或被引用物件。對物件的弱引用是一種不會阻止物件被垃圾回收器回收的引用。相比之下,普通(或強)引用會將物件保留在記憶體中。當一個物件不再有任何強引用指向它時,JavaScript 引擎的垃圾回收器可能會銷燬該物件並回收其記憶體。如果發生這種情況,您將無法再從弱引用中獲取該物件。
由於未註冊的 Symbol 也可以被垃圾回收,因此它們也可以用作 WeakRef 物件的 [目標](#target_object)。然而,這種用例是有限的。
儘可能避免使用
正確使用 WeakRef 需要仔細考慮,最好能避免就避免。同樣重要的是,要避免依賴規範未保證的任何特定行為。垃圾回收何時、如何發生以及是否發生取決於任何給定 JavaScript 引擎的實現。您在一個引擎中觀察到的任何行為,在另一個引擎、同一引擎的另一個版本,甚至在同一引擎的同一版本中的一個略有不同的情況下,都可能有所不同。垃圾回收是一個棘手的問題,JavaScript 引擎的實現者們正在不斷完善和改進他們的解決方案。
以下是引入 WeakRef 的提案中作者提出的一些具體要點:
垃圾回收器很複雜。如果應用程式或庫依賴於 GC 以及時、可預測的方式清理 WeakRef 或呼叫最終項 [清理回撥],它可能會感到失望:清理可能比預期發生得晚得多,甚至根本不發生。導致不確定性的因素包括:
- 一個物件可能比另一個物件更早被垃圾回收,即使它們同時變得不可達,例如,由於分代收集。
- 可以使用增量和併發技術將垃圾回收工作分解到一段時間內。
- 可以使用各種執行時啟發式方法來平衡記憶體使用和響應能力。
- JavaScript 引擎可能持有對看起來是不可達內容的引用(例如,在閉包或內聯快取中)。
- 不同的 JavaScript 引擎可能以不同的方式處理這些問題,或者同一引擎可能在其版本之間更改其演算法。
- 複雜因素可能導致物件被意外地長時間保持活動狀態,例如與某些 API 一起使用。
關於 WeakRef 的注意事項
- 如果您的程式碼剛剛為目標物件建立了一個
WeakRef,或者透過WeakRef的deref方法獲取了一個目標物件,那麼該目標物件將不會被回收,直到當前 JavaScript 任務(包括在指令碼任務結束時執行的任何 Promise 反應任務)結束。也就是說,您只能在事件迴圈的輪次之間“看到”物件被回收。這主要是為了避免讓任何給定 JavaScript 引擎的垃圾回收器行為在程式碼中變得明顯——因為如果它變得明顯,人們就會編寫依賴於該行為的程式碼,而當垃圾回收器的行為發生變化時,這些程式碼就會中斷。(垃圾回收是一個棘手的問題;JavaScript 引擎的實現者們正在不斷完善和改進其工作方式。) - 如果多個
WeakRefs 指向同一個目標,它們之間是保持一致的。在一個任務中,呼叫其中一個的deref所得到的結果將與呼叫另一個的deref所得到的結果匹配,您不會從一箇中得到目標物件,而從另一箇中得到undefined。 - 如果
WeakRef的目標也位於一個FinalizationRegistry中,那麼WeakRef的目標會在任何與登錄檔相關的清理回撥被呼叫時或之前被清除;如果您的清理回撥呼叫了目標物件的WeakRef的deref,它將收到undefined。 - 您無法更改
WeakRef的目標,它始終只會是原始目標物件,或者在目標物件被回收後為undefined。 - 即使沒有任何強引用指向目標物件,
WeakRef對deref的呼叫也可能永遠不會返回undefined,因為垃圾回收器可能永遠不會決定回收該物件。
建構函式
WeakRef()-
建立一個新的
WeakRef物件。
例項屬性
這些屬性定義在 WeakRef.prototype 上,並由所有 WeakRef 例項共享。
WeakRef.prototype.constructor可選-
建立例項物件的建構函式。對於
WeakRef例項,初始值是WeakRef建構函式。注意:此屬性在規範中被標記為“規範可選”,這意味著符合規範的實現可能不會暴露
constructor屬性。這可以防止任意程式碼獲取WeakRef建構函式並能夠觀察垃圾回收。然而,所有主流引擎預設都會暴露它。 WeakRef.prototype[Symbol.toStringTag]-
[Symbol.toStringTag]屬性的初始值是字串"WeakRef"。此屬性用於Object.prototype.toString()。
例項方法
WeakRef.prototype.deref()-
返回
WeakRef物件的目標物件,如果目標物件已被回收,則返回undefined。
示例
使用 WeakRef 物件
此示例啟動一個在 DOM 元素中顯示的計數器,當元素不再存在時停止。
class Counter {
constructor(element) {
// Remember a weak reference to the DOM element
this.ref = new WeakRef(element);
this.start();
}
start() {
if (this.timer) {
return;
}
this.count = 0;
const tick = () => {
// Get the element from the weak reference, if it still exists
const element = this.ref.deref();
if (element) {
element.textContent = ++this.count;
} else {
// The element doesn't exist anymore
console.log("The element is gone.");
this.stop();
this.ref = null;
}
};
tick();
this.timer = setInterval(tick, 1000);
}
stop() {
if (this.timer) {
clearInterval(this.timer);
this.timer = 0;
}
}
}
const counter = new Counter(document.getElementById("counter"));
setTimeout(() => {
document.getElementById("counter").remove();
}, 5000);
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-weak-ref-objects |
瀏覽器相容性
載入中…