Set性能最高,因其是V8深度优化的原生哈希结构,插入与查找均为O(1),整体O(n);而indexOf/includes/双重循环均为O(n²),实测10万元素耗时超800ms。

大数组去重性能最高的是 new Set(),实测 10 万元素数字/字符串数组,耗时约 10–15ms;次优是 Map 标记法(15–20ms),适合对象数组按字段去重;而 filter + indexOf 或 reduce + includes 在同样规模下要 800ms 以上,不适用于大数据量。
为什么 Set 性能最高
Set 是浏览器原生实现的哈希表结构,插入和查找平均时间复杂度都是 O(1),整个去重过程只需单次遍历(O(n))。它不依赖 JS 层循环嵌套,也没有重复扫描开销,V8 引擎对其做了深度优化。
- 对比
indexOf:每次调用都要从头遍历数组,实际是 O(n²) - 对比
includes:同理,内部仍需线性查找 - 对比双重 for 循环:显式两层遍历,算法复杂度固定为 O(n²)
- Set 不做值比较,只依赖 SameValueZero 规则(支持
NaN === NaN),判断极快
怎么科学测试性能
别只看 console.time 一次结果——随机波动大。正确做法是:
- 用
performance.now()替代console.time,精度达微秒级 - 每种方法跑 5–10 轮,取中位数或平均值,排除 GC、CPU 抢占干扰
- 测试数据要贴近真实场景:比如 10 万长度、含重复率 30% 的数字数组;或带 id 字段的 5 万对象数组
- 清空内存再测:每次测试前用
arr = null; gc?.()(Chrome DevTools 中可手动触发垃圾回收)
示例代码:
const arr = Array.from({length: 100000}, (_, i) => i % 8000); // 造含重复的数据let times = [];
for (let i = 0; i const start = performance.now();
const unique = [...new Set(arr)];
times.push(performance.now() - start);
}
console.log('Set 平均耗时:', (times.reduce((a, b) => a + b) / times.length).toFixed(2) + 'ms');
对象数组的大数据去重怎么做
Set 对对象无效(引用不同即视为不同),但可以用 Map 模拟哈希表,按指定 key 去重,仍是 O(n):
- 用
Map存 key(如item.id)→ 布尔值或 item 本身 - 配合
filter一次性完成:遇到未登记的 key 就记录并保留,已存在则跳过 - 避免用
findIndex或some,它们内部遍历会退化成 O(n²)
示例:
function uniqueById(arr) {const seen = new Map();
return arr.filter(item => {
if (seen.has(item.id)) return false;
seen.set(item.id, true);
return true;
});
}
还要注意这些细节
- 如果数组含
undefined、null、Symbol,Set 和 Map 都能正确保留唯一值 - IE 浏览器不支持 Set,若需兼容,可用 Object 键模拟(
obj[item] = true),但要注意 key 类型转换(如1和'1'会冲突) - 内存占用:Set/Map 会额外申请空间,10 万元素约多占 2–3MB,一般无压力;极端场景可考虑 in-place 修改(如排序后双指针),但会破坏原顺序



















