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()更简洁 - 不支持 IE,若需兼容 IE11,改用
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
);
- 该写法时间复杂度 O(n²),小数组(Map 缓存已见
id,降到 O(n) - 别用
includes或indexOf判断对象,它们仍用===,无效
filter + indexOf 适合只处理原始值且需兼容老环境
在不支持 Set 的运行时(如某些微信小程序基础库、Node.js
立即学习“Java免费学习笔记(深入)”;
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)?选错依据,再高效的代码也白搭。











