最简去重方法是[...new Set(arr)],适用于基础类型;但Set不支持对象结构去重、IE不兼容、NaN可去重而+0/-0视为相等,混合类型需预处理。

直接用 new Set() 转数组就行
ES6 的 Set 构造函数天然去重,它只保留第一次出现的值,且能接受任意可迭代对象(包括数组)作为参数。所以最简写法就是:[...new Set(arr)] —— 一行搞定,不需要写循环或 filter。
Set 去重和 filter + indexOf 的关键区别
很多人习惯用 arr.filter((item, i) => arr.indexOf(item) === i),但这个方法有明显短板:
-
indexOf对每个元素都从头遍历,时间复杂度是 O(n²),大数据量时明显变慢 - 无法正确处理
NaN:因为NaN !== NaN,indexOf(NaN)永远返回 -1,导致所有NaN都被保留 -
Set明确把NaN视为相同值,只留一个 -
Set不区分+0和-0(它们在Set中被视为相等),这点和===一致
遇到对象数组怎么办?Set 失效了
new Set([{a:1}, {a:1}]) 会保留两个对象,因为对象比较的是引用地址,不是结构。这时候不能靠 Set 一行解决,必须手动提取唯一标识:
- 如果对象有唯一
id字段:Array.from(new Map(arr.map(item => [item.id, item])).values()) - 如果需要按结构去重(小数组):
arr.filter((item, i) => i === arr.findIndex(v => JSON.stringify(v) === JSON.stringify(item))),但注意JSON.stringify不能处理函数、undefined、循环引用 - 没有通用“一行解”,别硬套
Set
兼容性与隐式转换风险
Set 是 ES6 特性,现代浏览器和 Node.js ≥ 4 都支持,但 IE 完全不支持。如果项目需兼容 IE,不能直接用。
另外注意类型隐式转换问题:
-
new Set([1, '1'])会保留两个值(1和'1'),因为Set使用SameValueZero算法,不进行类型转换 - 如果业务上认为数字
1和字符串'1'应算重复,那Set就不适用,得先统一类型再处理 - 布尔值
true/false和数字1/0同理,不会自动合并
真正“一行去重”只适用于基础类型数组,且你清楚它的比较逻辑。对象、混合类型、老环境——这些地方一不留神就掉坑里。

















