Set 是当前最简洁可靠的数组去重方案,但仅基于引用相等;对象内容去重需自定义逻辑,如按 id 过滤或 JSON.stringify(有局限),核心在于明确相等性定义。
JavaScript 数组去重没有“银弹”,但 Set 是当前最简洁、可靠、且默认满足多数场景的方案;其他方法需根据是否保留顺序、是否处理对象、是否兼容旧环境等具体条件取舍。
Set + 扩展运算符是最常用写法这是现代 JS(ES6+)中最推荐的写法,代码短、可读性强、性能好、自动去重原始值和引用值(注意:对象去重只看引用,不深比较)。
const arr = [1, 2, 2, 3, '3', '3', {}, {}];
const unique = [...new Set(arr)];
// → [1, 2, 3, '3', {}, {}](两个空对象仍被保留,因引用不同)
Set 构造时自动过滤重复值,仅对 === 相等的值生效[...] 将 Set 转回数组,比 Array.from() 更简洁Array.from(new Set(arr))
Set
当数组含对象、嵌套结构,且你希望按内容去重(如两个 {id: 1} 视为重复),Set 失效——它只认内存地址。此时必须手动遍历 + 序列化或自定义比较逻辑。
JSON.stringify 辅助去重,但有严重限制:键序敏感、无法处理函数/undefined/Symbol/循环引用/Date/RegExp 等findIndex 配合自定义判断,例如按 id 去重:const arr = [{id: 1}, {id: 2}, {id: 1}, {id: 3}];
const unique = arr.filter((item, index) =>
arr.findIndex(v => v.id === item.id) === index
);
id,降到 O(n)includes 或 indexOf 判断对象,它们仍用 ===,无效filter + indexOf 适合只处理原始值且需兼容老环境在不支持 Set 的运行时(如某些微信小程序基础库、Node.js
const arr = [1, 2, 2, 3, '3', '3']; const unique = arr.filter((item, index) => arr.indexOf(item) === index);
indexOf 返回首次出现位置,所以只对原始值(number/string/boolean/null/undefined)稳定有效NaN 会失效([NaN].indexOf(NaN) === -1),若需支持 NaN,得额外判断 Number.isNaN()
Set 差,尤其长数组;但代码无依赖,移植性极强真正容易被忽略的是「去重依据」本身:你以为在去重数组,其实是在选择一种相等性
定义——是严格相等(===)、字符串一致(JSON.stringify)、还是业务字段唯一(如 id)?选错依据,再高效的代码也白搭。