该用 weakmap 还是 map 取决于缓存对象生命周期是否需与业务解耦及是否需主动控制:对象可能被外部释放(如 dom 节点、组件实例)则选 weakmap,避免内存泄漏;需精确控制、遍历或调试缓存则选 map。

缓存是否该用 Map 还是 WeakMap,关键看两点:缓存对象的生命周期是否应与业务逻辑解耦,以及你是否需要主动控制缓存的存续。
缓存对象本身可能被外部释放?用 WeakMap
当缓存的键是 DOM 节点、事件监听器绑定的目标对象、或某个组件实例(比如 Vue 的 setup 返回对象),而这些对象在业务中可能随时被销毁(如组件卸载、节点移除),你就不能让缓存强行“拽住”它们不放——否则它们无法被垃圾回收,造成内存泄漏。
- WeakMap 的键是弱引用,一旦该对象在别处失去所有引用,GC 就能清理它,同时对应条目自动从 WeakMap 中消失
- 不需要手动调用
delete或维护清理逻辑,天然适配“随对象消亡而失效”的缓存语义 - 典型场景:为每个 DOM 元素缓存其计算样式、拖拽状态、表单校验结果
需要精确控制缓存生命周期?用 Map
如果你的缓存目标是长期稳定的对象(如配置项、用户会话数据、API 响应结果),或者键是字符串、数字等原始值,那就必须选 Map。
- Map 支持任意类型作键,包括
'user_123'、42、Symbol('token') - 提供
size、clear()、keys()、forEach()等完整 API,方便做容量限制、过期淘汰、批量刷新 - 适合实现 LRU 缓存、带 TTL 的响应缓存、多级缓存中间层
是否需要遍历或调试缓存内容?只能用 Map
WeakMap 不暴露任何遍历接口,也没有 size 属性。这意味着你无法:
- 检查当前缓存了多少条目
- 打印全部缓存键用于排查问题
- 按条件批量删除(例如“清除所有 user 相关缓存”)
- 在开发工具中直接查看内容(DevTools 对 WeakMap 显示为空或不可展开)
如果项目有可观测性要求、需配合监控埋点,或团队调试习惯依赖缓存快照,Map 是唯一可行选择。
是否与其他框架底层机制耦合?优先匹配设计意图
Vue 3 的响应式系统大量使用 WeakMap 存储 reactive 对象与依赖收集器(Dep)的映射;React 的 Fiber 节点元数据也倾向用 WeakMap 关联。如果你在封装类似能力(如自定义 hook 的状态隔离、私有字段模拟),沿用 WeakMap 更符合生态惯例,且避免意外干扰 GC。
- WeakMap 天然适合“附属元数据”:只服务于主对象,不改变其生命周期
- Map 更适合“独立资源管理”:缓存本身就是一个有明确生命周期的实体











