回归基本功:Map/Set 与 WeakMap/WeakSet 的区别

Map、Set、WeakMap、WeakSet 都是 ES6 引入的集合类型,它们的关系如下:

  • SetMap :标准的键值对或值的集合,对键/值是强引用,提供遍历、大小、清空等完整 API。
  • WeakMapWeakSet :只能以对象 作为键(WeakSet 的值也必须是对象),且持有的是弱引用 ,不可遍历,没有 size 属性。

一、Map vs WeakMap

特性 Map WeakMap
键的类型 任意类型(对象、基本类型等) 必须是对象(不能是 null)
值类型 任意 任意
引用类型 对键和值都是强引用 对键是弱引用,值平时是强引用(但当键被回收后,值也会被回收)
是否可迭代 可迭代(for...offorEach 不可迭代
获取大小 map.size 没有 size 属性
方法 set, get, has, delete, clear, keys(), values(), entries() set, get, has, delete (无 clear、无遍历方法)
何时使用 需要存储键值对,并且可能需要遍历或查看大小 需要为对象关联额外数据,且这些数据在对象消失后应自动清理

弱引用意味着什么?

js 复制代码
let obj = { name: 'Alice' };
const wm = new WeakMap();
wm.set(obj, 'private data');
console.log(wm.get(obj)); // 'private data'

obj = null; // 移除对原对象的强引用
// 此时,原对象没有其他强引用,垃圾回收器会回收它,WeakMap 中的条目也会自动消失(即使关联了私有数据)

为什么 WeakMap 不可遍历?

因为垃圾回收的执行时机不确定,WeakMap 的内容随时可能变化。如果提供迭代功能(forEachsize 等),你会得到一个不稳定的快照,容易产生错误。

经典用途:

  • 为 DOM 元素关联私有数据,当元素被移除后自动释放。
  • 实现类的私有属性(通过实例作为键)。

二、Set vs WeakSet

特性 Set WeakSet
值的类型 任意类型 必须是对象
引用类型 对值是强引用 对值是弱引用
是否可迭代 可迭代 不可迭代
获取大小 set.size 没有 size
方法 add, has, delete, clear, keys(), values(), entries() add, has, delete (无 clear、无遍历方法)
何时使用 需要存储不重复的值,或进行集合运算 存储对象是否存在,不关心遍历,且对象消失后应自动移除

实例

js 复制代码
let user1 = { name: 'Alice' };
let user2 = { name: 'Bob' };
const ws = new WeakSet([user1, user2]);
console.log(ws.has(user1)); // true

user1 = null; // 移除强引用后,user1 对应的对象被回收,WeakSet 中的记录也消失

三、核心区别总结

Map Set WeakMap WeakSet
存储结构 键值对 唯一值 键值对(键必为对象) 唯一值(值必为对象)
键/值要求 键任意 值任意 键必须对象 值必须对象
引用强度 强引用 强引用 弱引用(键) 弱引用(值)
可迭代性 可迭代 可迭代 不可迭代 不可迭代
size
clear()
典型场景 缓存、字典 去重、集合操作 DOM 关联数据、私有属性 对象标记、防止重复

四、何时用 WeakMap/WeakSet?

  • 内存敏感且不需要统计全部信息时,使用弱引用结构可以避免手动清理,减少内存泄漏风险。
  • 如果你需要遍历、检查大小或清空整个集合,那就必须用 Map/Set。

比如在 Web 应用中,一个页面可能有成千上万个动态 DOM 元素,为每个元素绑定的数据使用 WeakMap,当元素被移除后,占用的内存自动释放,比手动清除方便且安全。

相关推荐
程序员黑豆17 分钟前
鸿蒙应用开发 @Builder 使用教程:从入门到精通
前端·harmonyos
飛行艇18 分钟前
08 千人千面:Agent用户记忆与上下文管理
面试
CCYe、25 分钟前
限流与配额:企业AI网关的工程实践
前端·人工智能
看谷秀33 分钟前
arkts- 6 手势/沉浸式/深浅色/性能/组件补充/访问/js交互/通知/Native交互
前端·arkts
划船不慎掉水顺便摸鱼35 分钟前
TipTap 不是编辑器,是编辑器构造器:ProseMirror 模型驱动的富文本架构
前端
小高00741 分钟前
🔥🔥🔥TypeScript 7 正式版来了:别只看 10 倍速度,这 4 个迁移坑更值得注意
前端·javascript·面试
凉茶社1 小时前
shadcn/ui 默认改用 Base UI,Radix 被放弃了吗?
前端
Vuji1 小时前
ReAct 与 Plan-Execute:两种 Agent 范式的实战对比
前端·agent
用户61595868000221 小时前
从零原生搭建一个微前端简易框架
前端
小月土星1 小时前
React + TypeScript 企业级开发实战:从类型约束到组件设计
前端