set去重核心是利用其唯一性特性,一次遍历完成;基础写法为[...new set(arr)]或array.from(new set(arr)),时间复杂度o(n);对象数组需配合map或json.stringify实现字段级去重。

用 Set 实现数组去重,核心就一句话:把数组转成 Set,再转回数组。它不是“黑魔法”,而是利用了 Set 本身只存唯一值的天然特性,一次遍历就能完成,不用嵌套循环、也不用手动比对。
基础写法:两行搞定原始类型去重
适用于数字、字符串、布尔值、undefined、null、Symbol 和 NaN(注意:NaN 在 Set 中会被自动视为相同,只留一个):
- 用扩展运算符:const unique = [...new Set(arr)]
- 用 Array.from():const unique = Array.from(new Set(arr))
两种写法效果一致,都先创建 Set 实例(自动剔除重复),再还原为普通数组。底层基于哈希表,时间复杂度稳定在 O(n),远优于传统 indexOf + for 循环的 O(n²)。
对象数组去重:不能直接用 Set,得加一层映射
Set 对对象是按引用比较的,所以 [{a:1}, {a:1}] 会被当作两个不同元素。想按某个字段(比如 id)去重,得借助 Map 或字符串化:
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
- 按字段去重(推荐,不依赖 JSON 序列化):Array.from(new Map(arr.map(item => [item.id, item])).values())
- 通用字符串化方案(适合结构简单、无函数/undefined/Date 等):arr.map(JSON.stringify).filter((item, i, arr) => arr.indexOf(item) === i).map(JSON.parse)
第一种更健壮,Map 的键支持任意值,且保留原对象引用;第二种易读但有局限性,慎用于生产环境复杂数据。
几个关键细节别踩坑
Set 去重看着简单,但这些行为直接影响结果:
-
严格相等(===)判断:
1和"1"被认为不同,不会被去重 -
NaN 特殊处理:
new Set([NaN, NaN])大小为 1,这是规范定义,不是 bug - 对象靠引用:哪怕两个对象字面量完全一样,只要内存地址不同,Set 就全收
- 保持插入顺序:去重后数组顺序与原数组首次出现顺序一致,这点很实用
什么时候不该用 Set?
不是所有去重场景都适合 Set:
- 需要自定义比较逻辑(比如忽略大小写、四舍五入后比较)→ 改用
filter + findIndex或 reduce - 多维嵌套数组或含函数/正则/日期的对象 → JSON.stringify 可能失效,需手写深比较
- 老浏览器兼容要求(IE 全系不支持)→ 需配合 Babel 或降级方案










