Set配合扩展运算符是去重最简洁高效且保序的方法,适用于基本类型或浅层引用去重;对象数组按字段去重推荐用Map;复杂逻辑可用自定义keyFn的通用函数。

用 Set 配合扩展运算符是最简洁、高效且保持顺序的方法。
使用 Set + 扩展运算符(推荐)
Set 会自动去重,且按插入顺序保存元素;转回数组时顺序完全保留。
适用场景:数组元素全是基本类型(string、number、boolean、null、undefined、symbol)或想对引用类型做「浅层唯一性判断」(即只去重相同引用)。
- ✅ 保持原顺序
- ✅ 代码简短:
[...new Set(arr)] - ❌ 不适用于对象/数组等引用类型的内容去重(因
Set比较的是引用,不是值)
示例:
立即学习“Java免费学习笔记(深入)”;
const arr = [1, 2, 2, 3, 1, 4]; const unique = [...new Set(arr)]; // [1, 2, 3, 4]
针对对象数组按某字段去重
当数组由对象组成,需按某个属性(如 id 或 name)去重时,可用 Map 或 filter + findIndex。
推荐用 Map:一次遍历,性能好,顺序自然保留。
- ✅ 按指定 key 去重,不依赖引用
- ✅ 保持首次出现的顺序
- ✅ 支持任意类型字段(字符串、数字均可)
示例(按 id 去重):
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice2' },
{ id: 3, name: 'Charlie' }
];
const seen = new Map();
const uniqueUsers = users.filter(item => {
if (seen.has(item.id)) return false;
seen.set(item.id, true);
return true;
});
// [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' }]
通用函数:支持自定义比较逻辑
若需更灵活的去重(如忽略大小写、按多个字段、深比较等),可封装一个带回调的函数。
核心思路:遍历原数组,用结果数组记录已见过的「特征值」,跳过重复项。
- ✅ 完全可控,适配各种业务规则
- ✅ 仍保持原始顺序
- ✅ 可缓存中间键,避免重复计算
示例(忽略大小写的字符串去重):
function uniqueBy(arr, keyFn) {
const seen = new Set();
return arr.filter(item => {
const key = keyFn(item);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
const words = ['Apple', 'banana', 'apple', 'Cherry'];
const uniqueWords = uniqueBy(words, str => str.toLowerCase());
// ['Apple', 'banana', 'Cherry']
不推荐的方式提醒
避免用 indexOf / includes 在循环中查重:时间复杂度 O(n²),大数据量明显变慢。
避免用 reduce + includes:虽简洁但同样低效,且可读性未必更好。
不要用 filter + indexOf === index:仅对基本类型有效,且内部仍多次遍历,不如 Set 直观高效。


















