应优先使用set当需自动去重+快速存在性判断,而非仅要无重复数组;它适用于防重复提交、动态维护唯一项、集合运算及nan/对象引用去重,但不支持索引访问和数组高阶方法。

JavaScript 的 Set 是专为“唯一性”和“存在性判断”设计的原生集合,不是数组的简化版或升级版——它解决的是不同问题。去重只是它最直观的用途,但真正决定是否该用 Set 的,是你是否需要自动排重 + 快速查存,而不是单纯想要一个“没有重复的数组”。
核心区别:不是“能不能去重”,而是“为什么去重”
数组允许重复、支持索引、保留顺序、提供 map/filter/sort 等丰富方法;Set 天然拒绝重复、不支持索引(set[0] 无效)、不保证遍历顺序(尽管实际多按插入序)、没有高阶函数,但提供 add()、has()、delete() 这类语义清晰的集合操作。
- 数组去重是“结果导向”:你最终要一个无重复的数组,过程可手动(
filter + indexOf)或借助 Set([...new Set(arr)]) - Set 去重是“行为导向”:你在添加时就拒绝重复,且后续能用
has()在 O(1) 时间确认某值是否已存在
该用 Set 去重的典型场景
当去重只是起点,后续还需频繁判断、增删、或做集合运算时,Set 就比“去重后转回数组”更合适:
-
防重复提交或日志采集:维护一个
const submittedIds = new Set(),每次提交前调用submittedIds.has(id),比在长数组里反复includes()快得多 -
动态维护唯一项列表:比如用户勾选的标签、已加载的模块名,用
add()和delete()直接操作,无需担心重复或查找索引 -
做交集、差集等集合运算:例如获取两个用户权限的共同部分:
const common = new Set([...setA].filter(x => setB.has(x))) -
处理 NaN 或对象引用去重:Set 使用 Same-value-zero 算法,
new Set([NaN, NaN])只存一个 NaN;而数组indexOf(NaN)永远返回 -1,无法正确去重
用 Set 去重的常见写法与注意事项
最简去重写法是 [...new Set(arr)] 或 Array.from(new Set(arr)),但它只对原始值(数字、字符串、布尔等)有效:
- 对对象或数组等引用类型,Set 仍按内存地址判重:两个内容相同但新建的对象
{a:1}和{a:1}会被视为不同元素 - 若需按内容去重对象,得配合 Map 存序列化键,或用其他策略,不能直接依赖 Set
- Set 不保留“逻辑顺序”以外的排序,如需升序/降序结果,仍需转数组后调用
sort()
什么时候不该用 Set 做去重?
如果业务强依赖以下能力,就别硬套 Set:
- 需要按位置读写元素(如
arr[2] = 'x') - 必须使用
map、reduce、findIndex等数组专属方法 - 去重后立刻要排序、分组、或参与复杂链式数据流处理
- 数据量极小(如个位数),性能差异可忽略,代码可读性更重要
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











