WeakMap 防止内存泄漏的核心在于键为弱引用:只要对象无其他强引用,GC 即刻回收该对象及对应条目;而 Map 的强引用会阻止 GC,导致 detached DOM 等内存泄漏。

WeakMap 防止内存泄漏的核心,在于它对键(key)使用弱引用——只要 DOM 节点或类实例在其他地方没了强引用,哪怕 WeakMap 里还“记着”,它也能被垃圾回收器立刻清理掉,对应的数据条目自动消失。
WeakMap 的键不阻止 GC
普通 Map 或 Object 会对键做强引用:一旦你把一个按钮节点存进 Map,即使它已被 removeChild() 移出页面,只要 Map 还持有它,这个按钮连同整个子树就一直留在内存里,形成 detached DOM 树。
WeakMap 不一样:它不计入引用计数。节点从 DOM 移除后,若全局或闭包中再无其他变量指向它,GC 就能直接回收,WeakMap 中的那条记录也同步失效。
- DOM 节点被
innerHTML = ''清空 → 自动清理 - 组件卸载、路由跳转导致节点被销毁 → 自动清理
- 手动调用
element.remove()→ 自动清理
只适用于对象键,且必须是真实节点或实例
WeakMap 的 key 必须是对象(如 document.querySelector('button')),传字符串、数字或 null 会直接报错:TypeError: Invalid value used as weak map key。
立即学习“Java免费学习笔记(深入)”;
实际使用时建议加一层校验:
- 先判断节点是否存在:
if (btn && btn.nodeType === 1) - 避免误传 Window、Array 或普通对象
- 推荐在模块顶层声明单例 WeakMap,不要每次函数调用都新建
值仍是强引用,注意别自己“拖住”对象
WeakMap 只弱化键的引用,值(value)还是强引用。如果存进去的对象里又反向持有 this 或 DOM 节点,照样会造成泄漏。
- ❌ 错误:
weakMap.set(btn, { owner: btn, handler: () => {...} }) - ✅ 推荐:只存轻量状态,如
{ loading: true, count: 0 } - 事件监听器尽量用一次性绑定,或确保回调不意外捕获外部大对象
不能遍历,也不提供 size,但这恰恰是安全的前提
WeakMap 没有 keys()、values()、entries() 或 size,因为它内部状态随时可能因 GC 改变。这种“不可枚举性”不是缺陷,而是弱引用机制的必然设计。
这意味着:
- 不适合做需要批量读取或主动清空的缓存
- 适合绑定生命周期——对象在,数据就在;对象亡,数据自消
- 调试时无法直接查看全部条目,但可通过
get(key)按需访问


















