在JavaScript开发中,处理数组数据时经常需要提取其中的唯一元素,也就是去除数组中重复的项,得到所有不重复的元素集合。这个需求在数据统计、数据清洗等场景中非常常见,不同的实现方式在效率和适用性上有明显区别。

使用Set数据结构实现
Set是ES6引入的内置数据结构,它的特点就是成员值都是唯一的,没有重复的值,利用这个特性可以快速得到数组的唯一元素。实现逻辑非常简单,只需要把数组传入Set的构造函数,再把Set转回数组即可。
// 原始数组 const arr = [1, 2, 2, 3, 4, 4, 5]; // 使用Set去重 const uniqueArr = [...new Set(arr)]; console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]
这种方法的代码量最少,可读性也很高,而且Set底层做了专门的去重优化,在大部分场景下性能表现都很好。不过要注意,Set判断重复使用的是严格相等===,如果是对象类型的元素,只有引用完全相同的对象才会被判定为重复。
使用filter方法配合indexOf实现
filter方法可以遍历数组,筛选出符合条件的元素,结合indexOf方法可以判断当前元素是否是第一次出现在数组中,从而实现去重。
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.filter((item, index) => {
// indexOf返回当前元素第一次出现的索引,若等于当前索引说明是首次出现
return arr.indexOf(item) === index;
});
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]
这种方法的兼容性比Set更好,支持ES5及以上的环境,但是每次调用indexOf都需要遍历数组查找元素,时间复杂度是O(n²),当数组长度较大时性能会明显下降。
使用reduce方法实现
reduce方法可以对数组的每个元素执行回调函数,逐步累积计算结果,也可以用来实现数组去重。我们可以定义一个初始为空数组的累积值,遍历原数组时判断当前元素是否已经在累积值中,不在就加入。
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, cur) => {
// 判断累积数组中是否包含当前元素
if (!acc.includes(cur)) {
acc.push(cur);
}
return acc;
}, []);
console.log(uniqueArr); // 输出 [1, 2, 3, 4, 5]
这种方法的逻辑比较灵活,可以在去重的同时做其他数据处理操作,但是同样存在遍历查找的问题,includes方法的查找也需要时间,整体性能比Set方法稍差。
不同方法性能对比
我们可以通过一段简单的测试代码对比不同方法的执行效率,这里用长度为10000的随机数组做测试:
// 生成长度为10000的随机数组
const testArr = Array.from({ length: 10000 }, () => Math.floor(Math.random() * 5000));
// 测试Set方法耗时
console.time('Set方法');
[...new Set(testArr)];
console.timeEnd('Set方法');
// 测试filter+indexOf方法耗时
console.time('filter+indexOf方法');
testArr.filter((item, index) => testArr.indexOf(item) === index);
console.timeEnd('filter+indexOf方法');
// 测试reduce+includes方法耗时
console.time('reduce+includes方法');
testArr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
console.timeEnd('reduce+includes方法');
多次测试的结果显示,Set方法的耗时通常是另外两种方法的几十分之一甚至更低,在处理大数组时优势非常明显。如果项目环境支持ES6,优先选择Set方法实现数组唯一元素查找。
特殊场景的注意事项
如果数组中包含NaN元素,需要注意不同方法的差异。Set可以正常去重NaN,因为Set认为NaN等于NaN,而indexOf和includes无法判断NaN的重复,因为NaN === NaN返回false。
const arrWithNaN = [1, NaN, NaN, 2]; console.log([...new Set(arrWithNaN)]); // 输出 [1, NaN, 2] console.log(arrWithNaN.filter((item, index) => arrWithNaN.indexOf(item) === index)); // 输出 [1, NaN, NaN],无法去除NaN重复
如果数组中包含对象元素,所有方法都只能去除引用相同的对象,内容相同但引用不同的对象不会被判定为重复,如果需要按对象内容去重,需要额外处理对象的对比逻辑。
JavaScript数组唯一元素数组去重Set数据结构filter方法修改时间:2026-06-21 21:30:24