weakset 依靠弱引用机制不阻止对象垃圾回收,只用于标记对象是否处理过。它不存原始值、无遍历方法和 size 属性,适合防重复事件绑定或初始化,不能当缓存使用。

WeakSet 只存对象引用、且不干扰垃圾回收,靠的是“弱引用”机制——它不计入 JavaScript 引擎对对象的引用计数。只要对象在 WeakSet 外没有其他强引用,GC 就能随时把它回收掉。
为什么 WeakSet 不会阻止回收
普通集合(比如 Set)持有对象是强引用:只要对象还在 Set 里,哪怕页面其他地方早已不用它,GC 也不敢动。WeakSet 则不同——它对所存对象不做“计数贡献”。引擎只看外部是否还有变量、属性、闭包等在用这个对象。没有就回收,WeakSet 里的条目自动消失。
- WeakSet 内部不暴露遍历能力(无
keys()、values()、forEach),也没有size属性,正是因为它的内容随时可能被 GC 清掉,无法稳定统计 - 你调用
weakSet.has(obj)返回false,未必是没加过,可能是 obj 已被回收了 - WeakSet 不能存原始值(数字、字符串、
null、undefined),因为弱引用只对对象有效
典型安全用法:标记而非持有
WeakSet 最自然的角色是“打标签”,不是“存数据”。它适合记录“这个对象我处理过了吗?”这类瞬时状态,不保存实际信息。
- 防重复绑定事件:
if (!processed.has(el)) { processed.add(el); el.addEventListener('click', handler); } - 防重复初始化:
if (!inited.has(node)) { init(node); inited.add(node); } - 节点移除后,对应标记自动失效——不需要手动
delete,也不用担心残留
容易踩的坑
WeakSet 本身不泄漏,但你的使用方式可能绕过它的保护。
- 别把 WeakSet 当缓存用:它不提供取值能力(没有
get方法),也没法反查对象 - 别在别的地方保留对同一对象的强引用,还指望 WeakSet 能“帮它活下来”——WeakSet 不负责保命,只负责不拖后腿
- 别误以为
weakSet.add(obj)后 obj 就“安全了”:恰恰相反,它只是多了一个不计数的标记位
不复杂但容易忽略:WeakSet 的价值不在“存”,而在“不拦着回收”。用对场景,它就是一道安静的内存防火墙。











