weakmap 和 weakset 的核心作用是“不拦着回收”,即对象无其他强引用时,gc 可正常回收其在 weakmap 键或 weakset 中的条目;weakmap 适合为对象挂私有状态,weakset 仅用于标记对象是否存活。

WeakMap 和 WeakSet 的核心作用不是“存数据”,而是“不拦着回收”——对象只要没别的强引用,哪怕它还在 WeakMap 的键里、WeakSet 的集合中,GC 也能照常把它收走。关键在于用法是否符合弱引用语义。
WeakMap:给对象挂私有状态,不延长它的命
WeakMap 的键必须是对象,且只弱引用这个对象;值可以任意类型,但值本身仍是强引用。所以重点是别让值反过来 hold 住键。
- 只用对象作键,比如 DOM 元素、类实例、普通 object —— 字符串、数字、null 都会报错
- 避免在值里保存对键的反向引用(例如闭包捕获 this、值里存 this 的引用),否则形成循环,GC 就没法回收
- 适合场景:为第三方对象附加元数据(如配置、缓存、计数器),又不想干预它的生命周期
WeakSet:只问“它还在吗”,不存东西
WeakSet 不存“值”,只标记“这个对象是否曾被加进来过”。它没有 size、不能遍历、也不能 clear,恰恰是为了防止你误用它做持久存储。
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
- 只能 add 对象,不能 add 基本类型;has() 返回布尔值,告诉你对象当前是否还“活着”
- 典型用途:防重复处理(如初始化一次就标记)、跳过已参与计算的对象、记录活跃监听目标
- 一旦对象失去所有强引用,WeakSet 自动丢掉它,不需要你手动 delete 或清理
避开三个常见踩坑点
WeakMap/WeakSet 不是自动清内存的魔法开关,用错反而藏得更深:
- 别指望“立刻消失”:GC 时机不可控,条目可能短暂残留,逻辑上应视为“最终会清理”,而非“马上没了”
- 别把 WeakMap 当 Map 用:它不支持遍历、没有 keys()/values(),也不能序列化,调试时 console.log 只显示空壳
- 别混用 WeakSet 和普通 Set 做去重:WeakSet 无法保证“全局唯一性”,它只反映当前存活对象的状态,不适合数组去重等需要稳定结果的场景
一个真实可用的小模式
比如管理一组动态创建又销毁的组件实例:
- 用 WeakMap 存每个实例的内部状态(如 loading 标志、上次响应时间)
- 用 WeakSet 标记哪些实例正在执行异步操作,避免重复触发
- 组件卸载、变量置 null、DOM 移除后,两者都不需手动干预,关联数据自然失效










