WeakSet只能存储对象且为弱引用,不阻止垃圾回收,无size属性、不可遍历,仅支持add()、has()、delete()方法,适用于对象身份标记等临时状态跟踪场景。

WeakSet 只能存储对象(不能存原始值),且对所存对象保持弱引用——即不阻止垃圾回收器回收这些对象。只要对象在其他地方不再被引用,即使它还在 WeakSet 中,也会被自动移除。
WeakSet 的基本用法和限制
WeakSet 没有 size 属性,也不能遍历(没有 keys()、values()、entries() 或 forEach),这是为了防止暴露内部引用状态,确保“弱性”不被意外破坏。
- 只能用
add(obj)添加对象 - 只能用
has(obj)检查某个对象是否曾被加入(注意:若对象已被回收,has返回false) - 只能用
delete(obj)主动移除(但通常不需要,因为弱引用会自然失效) - 不能添加字符串、数字、null、undefined 等非对象值,否则报错
典型使用场景:标记已处理的对象
比如在深度遍历或事件监听中,避免重复处理同一对象:
const seen = new WeakSet();
function process(obj) {
if (seen.has(obj)) return;
seen.add(obj);
// 实际处理逻辑...
console.log('Processing:', obj);
// 若 obj 后续不再被其他变量引用,它可能随时被 GC 回收
// seen 内部不会阻止这一点
}
相比用普通 Set 存对象引用,WeakSet 不会造成内存泄漏——尤其适合临时标记、中间状态跟踪等生命周期不确定的场景。
立即学习“Java免费学习笔记(深入)”;
验证弱引用行为(需配合 GC 观察)
浏览器中无法直接触发 GC,但可通过以下方式间接验证:
- 创建一个对象,加入 WeakSet
- 将该对象变量设为
null,且无其他引用 - 稍后调用
has(),大概率返回false(取决于 GC 是否已运行)
例如:
const ws = new WeakSet();
let obj = { id: 1 };
ws.add(obj);
obj = null; // 切断唯一强引用
// 此时 ws.has({id: 1}) 仍为 false —— 因为新对象不是原对象
// 要检测原对象,必须保留引用(但那就不是“弱”了)
// 所以 WeakSet 的设计本意是:你只关心“我是否还持有它”,而不是“它是否还活着”
换句话说,WeakSet 不提供“对象是否存活”的可靠查询接口,而是让使用者接受“存在即有效,消失即不可见”的语义。
常见误区提醒
- WeakSet 不是缓存:不能靠它长期保存对象,也不支持迭代取值
- 不能替代 Map 或 Set 做键值映射:它没有键,只有对象成员身份
- 不能用于跨函数共享状态判断:如果两个函数各自新建 WeakSet,彼此不可知
- 与 WeakMap 区分清楚:WeakMap 用对象作键、任意值作值;WeakSet 只存对象,无值概念


















