当然可以!下面是【前端面试题】:JavaScript 数组去重的几种常见方法,涵盖基础写法、进阶技巧、性能对比与场景推荐,非常适合用于简历项目描述、技术博客、面试复习等场合。
🔍 [前端面试题]:JavaScript 数组去重的几种方法(含详细解析)
🧪 示例输入:
const arr = [1, 2, 2, 3, 4, 4, 5, '5', NaN, NaN, null, null, undefined, undefined];
✅ 方法一:使用 Set
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr);
📌 原理:
Set
是 ES6 新增的数据结构,天然去重。- 注意:
Set
去重是值相等,但不同类型不会去除(如5
与'5'
都保留)。
✅ 适合场景:
- 快速处理基本类型数组去重;
- 无需关心数据类型严格一致。
✅ 方法二:使用 filter + indexOf
const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(uniqueArr);
📌 原理:
indexOf
会返回第一个出现的位置,若当前位置不是第一次出现,则说明是重复项。- 缺点:性能较差,嵌套循环时间复杂度为 O(n²)。
✅ 适合场景:
- 面试展示思路时可用;
- 小数据量处理场景。
✅ 方法三:使用 reduce + includes
const uniqueArr = arr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
console.log(uniqueArr);
📌 原理:
reduce
控制遍历流程,includes
判断是否已存在。- 支持自定义逻辑扩展,如自定义比较函数。
✅ 适合场景:
- 适合展示函数式编程思维;
- 可变式逻辑适合扩展场景。
✅ 方法四:使用 Map
或 Object
缓存(高性能)
function unique(arr) {
const seen = new Map();
return arr.filter(item => {
return !seen.has(item) && seen.set(item, 1);
});
}
console.log(unique(arr));
📌 原理:
- 利用
Map
的键唯一性,实现一次遍历去重; - 相较
includes
、indexOf
性能更好,时间复杂度 O(n)。
✅ 适合场景:
- 中大型数组去重;
- 兼顾性能与清晰度。
✅ 方法五:处理复杂对象数组(按某字段去重)
const objArr = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 1, name: 'A' }
];
const uniqueObjArr = objArr.filter((item, index, self) =>
index === self.findIndex(t => t.id === item.id)
);
console.log(uniqueObjArr);
📌 原理:
- 利用
findIndex
查找首个匹配对象,保留唯一项。
✅ 适合场景:
- 对象数组去重,如根据 ID 唯一标识去重。
📊 性能对比总结
方法 | 性能 | 兼容性 | 简洁度 | 是否支持复杂数据 |
---|---|---|---|---|
Set | ★★★★ | ES6+ | ★★★★★ | 否(值比较) |
filter + indexOf | ★★☆ | ES5+ | ★★★ | 否 |
reduce + includes | ★★☆ | ES5+ | ★★★ | 否 |
Map | ★★★★ | ES6+ | ★★★★ | 否 |
对象数组去重 | ★★★ | ES5+ | ★★★ | ✅ 支持按字段 |
📌 面试加分点
- 了解时间复杂度:如
includes
是 O(n),而Set
查找是 O(1)。 - 熟悉基础类型和引用类型的去重差异。
- 能根据场景选择合适的方式(如
Map
用于高性能,filter
用于简单小数组)。
发表回复