javascript高效去重应优先用set处理基础类型,map处理任意类型或字段去重,object模拟需防类型混淆;核心是利用引擎优化的哈希机制而非手写哈希函数。

JavaScript 中手写高效去重函数,核心就是模拟哈希表(Hash Table)的 O(1) 平均查找/插入 特性——用对象(Object)、Map 或 Set 作底层存储,避免嵌套循环。关键不在“手写哈希函数”,而在于利用 JS 引擎已优化的键值映射机制来跳过重复项。
用 Map 实现稳定、通用的去重(推荐)
Map 保留插入顺序,支持任意类型键(包括对象、函数),且无原型链干扰,是最贴近哈希表语义的选择:
- 遍历原数组,以当前元素为 key 存入 Map(value 可设为 true 或索引)
- 再次遍历时只取 Map 中首次出现的 key(即 keys() 迭代器天然去重且有序)
- 比 Object 更安全:不会把数字索引转成字符串,也不受
toString()隐式调用影响
示例:
function uniqueByMap(arr) {
const seen = new Map();
const result = [];
for (const item of arr) {
if (!seen.has(item)) {
seen.set(item, true);
result.push(item);
}
}
return result;
}
用 Set 一行解决基础类型去重
Set 本质就是哈希表的封装,对字符串、数字、布尔等基础类型最简洁:
-
[...new Set(arr)]是最简写法,内部已用哈希策略保证唯一性和顺序 - 注意:Set 对象或数组等引用类型仍按内存地址比较,
{a:1}和{a:1}被视为不同 - 如需深比较对象,需额外序列化(如
JSON.stringify),但要注意键序、undefined、函数等限制
安全的对象数组去重(基于某字段):
function uniqueByField(arr, key) {
const seen = new Set();
return arr.filter(item => {
const val = typeof item === 'object' ? item[key] : item;
if (seen.has(val)) return false;
seen.add(val);
return true;
});
}
用对象模拟哈希表(兼容旧环境,慎用)
仅适用于字符串/数字/布尔等可安全转为字符串的键(因为对象属性名自动 toString):
- 用
obj[item] = true标记存在,再用for...in或Object.keys()提取 - 风险点:
0、false、''、null、undefined在 toString 后都变成'',会误判冲突 - 若必须用对象,建议统一前缀:
seen['$' + item]或用Object.create(null)避免原型污染
改进版(防类型混淆):
function uniqueByObj(arr) {
const seen = Object.create(null);
const result = [];
for (const item of arr) {
const key = typeof item + '|' + item; // 类型+值组合确保唯一
if (!seen[key]) {
seen[key] = true;
result.push(item);
}
}
return result;
}
性能与选型建议
实际开发中优先级:
- 基础类型 → 直接用
[...new Set(arr)](V8 优化极好,代码最简) - 需要按字段去重或兼容 IE → 用
Map(现代浏览器全覆盖,逻辑清晰) - 处理大量数据且对内存敏感 → 可考虑 in-place 原地去重(修改原数组,减少新建)
- 避免手动实现哈希函数(如取模、质数桶),JS 引擎已内置高性能哈希算法
不复杂但容易忽略:哈希表高效的前提是“均匀分布”,而 JS 的 Map/Set 已由引擎保障,你只需专注逻辑表达。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











