对象数组去重需基于字段值判断,推荐用map按单字段、嵌套路径或多字段联合去重,兼顾性能与健壮性;旧环境可用reduce+some但复杂度高。

对象数组不能直接用 Set 或 filter + indexOf 去重,因为对象是引用类型,两个内容相同的对象在内存中地址不同,会被视为不重复。必须提取字段值作为判断依据,再借助唯一性数据结构(如 Map 或 Set)来筛选。
用 Map 按单个字段去重(推荐)
利用 Map 的键唯一性,以目标字段值为 key、整个对象为 value,只保留首次出现的项。
- 代码简洁,性能好(O(n)),逻辑清晰
- 自动跳过
undefined或null字段值(不会报错,但需注意是否符合业务预期) - 若字段不存在,
item[field]返回undefined,多个对象都会被归到同一个undefined键下——建议加空值校验
示例:
const map = new Map();
for (const item of arr) {
if (item?.[field] !== undefined && !map.has(item[field])) {
map.set(item[field], item);
}
}
return Array.from(map.values());
};
支持嵌套字段路径(如 user.info.id)
当要按深层属性去重时,不能直接用点号访问,需安全取值函数避免报错。
- 用
path.split('.').reduce((cur, key) => cur?.[key], obj)安全获取嵌套值 - 同样配合
Map,保持首项优先原则 - 对
null、undefined、NaN等边界值仍需单独判断(例如Number.isNaN(key))
示例:
const get = (obj, path) => path.split('.').reduce((cur, key) => cur?.[key], obj);const uniqueByPath = (arr, path) => {
const map = new Map();
for (const item of arr) {
const key = get(item, path);
if (key !== undefined && key !== null && !Number.isNaN(key) && !map.has(key)) {
map.set(key, item);
}
}
return Array.from(map.values());
};
按多个字段联合去重(如 name + age)
需将多个值拼成唯一字符串键,避免歧义(如 '1' + '23' 和 '12' + '3' 冲突)。
- 推荐用分隔符拼接:`${item.name}|${item.age}`
- 也可用
JSON.stringify([item.name, item.age]),更稳妥但稍重 - 仍用
Map存键→对象,最后取.values()
示例:
const uniqueByMulti = (arr, fields) => {const map = new Map();
for (const item of arr) {
const key = fields.map(f => item[f]).join('|');
if (!map.has(key)) map.set(key, item);
}
return Array.from(map.values());
};
// 使用:uniqueByMulti(list, ['name', 'age'])
兼容旧环境的 reduce + some 方案
不依赖 Map,适合需支持 IE 或极老运行时的场景。
- 用
some()检查结果数组中是否已有相同字段值的对象 - 时间复杂度 O(n²),小数据量无感,大数据慎用
- 写法直观,容易调试和修改逻辑(比如改成保留最后一项)
示例:
const uniqueByField = (arr, field) => {return arr.reduce((res, item) => {
const exists = res.some(obj => obj[field] === item[field]);
return exists ? res : [...res, item];
}, []);
};











