https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
GC(garbage collector 垃圾收集器)
MDN 原话: Correct use of WeakRef takes careful thought, and it’s best avoided if possible. It’s also important to avoid relying on any specific behaviors not guaranteed by the specification. When, how, and whether garbage collection occurs is down to the implementation of any given JavaScript engine. Any behavior you observe in one engine may be different in another engine, in another version of the same engine, or even in a slightly different situation with the same version of the same engine. Garbage collection is a hard problem that JavaScript engine implementers are constantly refining and improving their solutions to.正确使用 WeakRef 对象需要仔细的考虑,最好尽量避免使用。避免依赖于规范没有保证的任何特定行为也是十分重要的。何时、如何以及是否发生垃圾回收取决于任何给定 JavaScript 引擎的实现。GC在一个 JavaScript 引擎中的行为有可能在另一个 JavaScript 引擎中的行为大相径庭,或者甚至在同一类引擎,不同版本中GC的行为都有可能有较大的差距。GC目前还是 JavaScript 引擎实现者不断改进和改进解决方案的一个难题。
**
const newRef = new WeakRef({ name: "dd", age: "100", sex: "boy" });
console.log(newRef.deref()); // {name: "dd", age: "100", sex: "boy"}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WeakRef</title>
</head>
<body>
<h1>WeakRef</h1>
<h2>DOM元素中启动一个计数器,当这个元素不存在时停止</h2>
<div id="counter"></div>
</body>
</html>
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
// 返回当前实例的WeakRef对象所绑定的target对象,如果该target对象已被GC回收则返回undefined
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"));
counter.start();
setTimeout(() => {
document.getElementById("counter").remove();
}, 5000);