Set 存对象易致内存泄漏,因其对成员为强引用,对象无法被垃圾回收;WeakSet 是更安全的替代方案,专用于标记对象且自动清理。

ES6 的 Set 本身不提供弱引用机制,它对所有成员(包括对象)都是强引用。这意味着:只要一个对象被塞进 Set,且该 Set 本身还“活着”(比如是全局变量、模块级常量或被其他活跃对象持有),这个对象就永远不会被垃圾回收(GC)——哪怕它在业务逻辑中早已“失效”,比如 DOM 节点已被移除、组件实例已卸载。
为什么 Set 存对象容易导致内存泄漏
Set 的设计目标是“值的唯一集合”,不是“临时标记工具”。它会牢牢 hold 住每个 add 进去的对象,不管这个对象是否还有其他用途。例如:
- 缓存 DOM 元素到全局 Set 中,但后续页面移除了这些节点,Set 却继续引用它们 → 节点无法 GC
- 在 React/Vue 组件中把 this 或响应式对象加入 Set,组件销毁后 Set 仍存在 → 实例残留
- 用 Set 做“已处理标记”,但忘了手动 delete,又没做生命周期清理 → 标记越积越多
替代方案:优先用 WeakSet 标记对象
如果目的只是“标记某个对象是否被处理过”“是否已注册”“是否需跳过”,WeakSet 是更安全、更自然的选择:
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
- 只接受对象,不接受基本类型(符合“标记对象”的语义)
- 对对象是弱引用:对象一旦失去其他强引用,WeakSet 中对应条目自动消失
- 没有 size、没有遍历能力(防止误用),天然规避长期持有风险
示例:
const processed = new WeakSet();function handleNode(node) {
if (processed.has(node)) return;
processed.add(node);
// ... 处理逻辑
}
若必须用 Set,就得主动管理生命周期
当 Set 确实需要承载业务数据(如待批量提交的对象列表、用户选中的实体集合),就不能依赖自动释放,而要配合明确的清理时机:
- 在对象“失效”时显式调用
set.delete(obj),比如组件unmounted钩子、DOMremove后、定时器清除前 - 避免将 Set 设为全局变量;尽量限制作用域,用闭包或模块私有变量封装
- 慎用
set.clear()—— 它清空全部,可能误删还在使用的项;优先按需 delete - 可搭配 WeakMap 记录清理回调(如:
weakMap.set(obj, () => set.delete(obj))),在对象销毁时触发
别混淆:WeakSet 不是 Set 的“轻量版”,而是不同用途
WeakSet 不支持遍历、没有 size、不能迭代,也不是为了替代 Set 的所有场景。它专为“临时关联 + 自动清理”而生。如果你需要:
- 去重数组 → 用 Set(没问题,数组短命,生命周期可控)
- 存储配置项、选项列表、状态集合 → 用 Set(数据稳定,本就不该被 GC)
- 标记 DOM/组件/临时对象是否已处理 → 用 WeakSet(防泄漏,零维护)

















