WeakMap 和 WeakSet 的核心价值是支持对象自动垃圾回收,适用于临时关联、标记或缓存。WeakMap 键弱引用、值强引用,适合绑定私有数据;WeakSet 全弱引用,仅用于防重复标记,二者均需单例封装且不可滥用强引用。

WeakMap 和 WeakSet 的核心价值在于让对象能被正常回收,而不是强行“锁住”内存。它们不阻止垃圾回收,所以适合做临时关联、标记或缓存,但不能当通用容器用。
WeakMap 适合绑定私有数据或元信息
它只对键弱引用,值仍是强引用——这点特别关键。如果你把整个组件实例塞进 value,而这个实例又反向持有 key(比如 DOM 节点里存了 this),照样泄漏。
- 键必须是对象,比如 class 实例或 DOM 元素;值尽量轻量:用简单对象、数字、布尔,别放大数组或闭包
- 常用于模拟私有属性:用一个模块级 WeakMap 存储每个实例的敏感字段,实例销毁时数据自动消失
- 给 DOM 节点加配置时优先选 WeakMap,节点被 remove 后,对应条目不会滞留
WeakSet 适合做“已处理”标记,不是计数器
它只存对象,且全部弱引用,没有 size、不能遍历、也不能 clear。这些限制恰恰保障了它不干扰 GC。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 典型用法是防重复:比如遍历树结构时,用 WeakSet 记录已访问节点,避免死循环,节点移除后标记自动失效
- 可用于事件监听去重:if (!observed.has(el)) { observed.add(el); el.addEventListener(...) }
- 不能用来统计数量,也不能批量操作——它天生就不支持这些
必须封装成单例,避免多个实例分散状态
每个 WeakMap 或 WeakSet 都是独立引用容器。如果在函数里反复 new,不仅浪费内存,还会导致同一类对象被多处标记,清理逻辑混乱。
立即学习“Java免费学习笔记(深入)”;
- 所有 WeakMap / WeakSet 应定义在模块顶层,作为 const 单例导出
- 不同用途要起不同名字,比如 privateState、processedNodes、activeTimers,别混用一个实例
- 不要在循环或频繁调用的函数中创建新实例
避开常见陷阱:值强引用和反向持有
WeakMap 的键虽弱,但值不是。WeakSet 里对象虽弱,但若外部还有强引用,它就不会被回收——弱引用不等于“立刻释放”。
- 禁止在 value 里写 { owner: node } 这类反向强引用
- 别把 get() 返回的对象传给 setInterval、全局数组或未注销的事件监听器
- WeakSet 不支持基本类型,传字符串或数字会直接报错,只能传对象

















