使用Set去重最简洁高效,适用于基本类型;2. Filter+indexOf兼容性好但性能较差;3. forEach+Object利用键值记录,需注意类型转换问题;4. map方式更安全可靠,支持任意键类型;5. reduce函数式风格清晰但性能一般;6. 排序后比较节省空间但改变顺序;7. jsON.Stringify用于对象数组去重但有局限性;8. 根据属性如id去重最常用且灵活;9. 双重循环适合理解原理但效率低;10. 利用symbol或WeakMap可实现更高级去重。

javaScript数组去重是开发中常见的需求,尤其在处理用户输入、接口返回数据或集合操作时。下面介绍十种高效且实用的数组去重方法,涵盖基础类型与引用类型的不同场景,帮助你在不同情况下选择最合适的方式。
1. 使用 Set 去重(最简洁)
es6 引入的 Set 数据结构自动保证元素唯一性,结合扩展运算符可快速实现去重。
const unique = […new Set(arr)];
适用于基本类型(number、string、Boolean),代码最短,性能优秀。
2. filter + indexOf(兼容性好)
利用 indexOf 返回第一个匹配项的索引,判断当前项是否首次出现。
立即学习“Java免费学习笔记(深入)”;
arr.filter((item, index) => arr.indexOf(item) === index);
适合老浏览器环境,但对长数组性能较差,因 indexOf 是 O(n) 操作。
3. foreach + Object 键值去重(适合基本类型)
使用普通对象作为哈希表记录已出现的值。
let obj = {};
let result = [];
arr.forEach(item => {
if (!obj[item]) {
obj[item] = true;
result.push(item);
}
});
注意:item 为数字或字符串时有效,true 和 ‘1’ 可能冲突,需谨慎处理类型。
4. Map 记录唯一值(推荐用于复杂判断)
Map 支持任意类型键值,比 Object 更安全。
const map = new Map();
const result = [];
arr.forEach(item => {
if (!map.has(item)) {
map.set(item, true);
result.push(item);
}
});
比 Object 方式更可靠,尤其在涉及多种数据类型时。
5. reduce 实现去重(函数式风格)
使用 reduce 累积唯一值。
arr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
代码清晰,但 includes 遍历导致性能一般,适合小数组。
6. 排序后相邻比较(节省空间)
先排序,再比较相邻元素。
arr
.slice()
.sort()
.filter((item, index, array) => index === 0 || item !== Array[index – 1]);
修改了顺序,不适合要求保持原序的场景,但空间利用率高。
7. 去重对象数组:json.stringify + Set
对对象数组可通过序列化判断是否重复。
[…new Set(arr.map(JSON.stringify))].map(JSON.parse);
简单粗暴,但属性顺序影响结果,且含函数或 undefined 会失败,慎用。
8. 根据对象特定属性去重
例如根据 id 去除重复对象。
const seen = new Set();
arr.filter(item => {
if (seen.has(item.id)) return false;
seen.add(item.id);
return true;
});
实际项目中最常用方式之一,灵活可控。
9. 双重循环 + 标志位(手动控制)
传统方式,适合学习理解原理。
let result = [];
for (let i = 0; i let isDuplicate = false;
for (let j = 0; j if (arr[i] === result[j]) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) result.push(arr[i]);
}
时间复杂度高,仅建议用于极小数据集或教学。
10. 利用 proxy 中间拦截(高级技巧)
可在数据写入过程中实时去重。
const uniqueArray = new Proxy([], {
set(target, Property, value) {
if (target.includes(value)) return true;
target[property] = value;
return true;
}
});
属于进阶用法,适合需要动态拦截赋值的场景。
基本上就这些。选择哪种方法取决于你的数据类型、性能要求和浏览器支持。多数情况下,Set 是首选方案,简洁高效;对象数组则推荐基于属性的 Map 过滤。不复杂但容易忽略的是数据类型的兼容性和原始顺序的保持。
以上就是javascript数组去重的十种高效方法_