回归基本功: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,当元素被移除后,占用的内存自动释放,比手动清除方便且安全。

相关推荐
IT乐手1 小时前
48队都装不下你|国足第24次让全世界失望
前端
SoaringHeart2 小时前
Flutter最佳实践:IM聊天文字链接自动识别跳转
前端·flutter
掘金一周3 小时前
企业中要做智能体,最佳的方案是什么? | 沸点周刊 6.18
前端·人工智能·ai编程
Darling噜啦啦3 小时前
CSS 3D 变换与 Flex 布局实战:从零打造旋转立方体
前端·css
秃头网友小李3 小时前
前端难点:keep-alive 缓存什么?RouterView 的 key 为什么要带 scopeId?
前端·vue.js
鱼人3 小时前
CSS 变量:一个变量救你一百次复制粘贴
前端
长大19884 小时前
CSS 到底是什么?和 HTML 的区别一次讲清楚
前端
禅思院4 小时前
路由性能优化终极指南:从懒加载漏洞到边缘渲染的架构跃迁
前端·架构·前端框架
怕浪猫4 小时前
Electron 开发实战(十六):总结与展望|生态现状、框架对比、行业趋势与学习指南
前端·javascript·electron