关于 WeakRef:
WeakRef对象允许保留对另一个对象的弱引用,而不会阻止或干扰该对象被GC回收。
它拥有一个 deref() 方法,
WeakRef.prototype.deref() 该方法的返回值是WeakRef对象所绑定的target对象(如果该target对象已被GC回收则返回 undefined)。
注意:在使用WeakRef过程中,容易出现坑。
因为如何回收、何时或者是否发生垃圾回收取决于代码所处环境中JavaScript引擎的实现。
比如,你可能以为在WeakRef的target对象不存在后,某些相关逻辑会被立即触发,但实际上这需要看target对象被回收的确切时间(可能会慢几秒,也可能。。)。
另外,如果你代码中有些地方不小心保持了对target对象的引用(如console.log了一下target对象),那么它实际上并没有被GC。
用法示例:
<body> <span id="counter-view"></span> <script> /* 计数器 */ class Counter { constructor(el) { // 元素引用 this.ref = new WeakRef(el); // 计时器 this.timer = void 0; // 计数值 this.count = 0; } /** * 开启计数 */ start() { if (typeof this.timer === 'number') return; /** * 计数 */ const tick = () => { // 获取被引用的对象(目标元素) const target = this.ref.deref(); // 如果目标元素已经被GC,则停止计数 if (target === undefined) { console.log('目标元素不存在了!'); this.stop(); this.ref = null; } else { target.textContent = ++this.count; } }; // 启动 tick(); this.timer = window.setInterval(tick, 1000); } /** * 停止计数 */ stop() { if (typeof this.timer === 'number') { this.timer = window.clearInterval(this.timer); } } /** * 卸载计数展示元素 */ unmount(seconds) { // 立即卸载或延迟卸载元素 if (seconds === undefined) { document.getElementById('counter-view').remove(); } else { window.setTimeout(() => { document.getElementById('counter-view').remove(); }, seconds * 1000); } } } /** * 初始化计数器 */ function initCounter() { const view = document.getElementById('counter-view'); if (view === null) { console.log('获取 Counter 元素失败!'); return; } const counter = new Counter(view); counter.start(); counter.unmount(6); } initCounter(); </script> </body>
MDN
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
End