javascript中对对象数组按字段去重需用map或reduce,避免引用比较;推荐map法保留首项,支持嵌套路径;注意null/undefined及非原始类型字段的特殊处理。

在 JavaScript 中对包含对象的复杂数组按指定字段去重,核心思路是:**提取唯一标识(如 id、name 等字段值),再借助 Set 或 Map 去重,最后还原数组项**。不能直接用 `filter` + `indexOf` 或 `includes`,因为对象引用不同,即使内容相同也会被当作不同元素。
用 Map 按字段键值去重(推荐,清晰且支持任意字段)
利用 `Map` 的键唯一性,以目标字段值为 key,整个对象为 value,自动去重(后出现的同 key 项会覆盖前面的;若要保留第一个,需检查 key 是否已存在)。
const uniqueByField = (arr, field) => {
const map = new Map();
for (const item of arr) {
if (!map.has(item[field])) {
map.set(item[field], item);
}
}
return Array.from(map.values());
};
✅ 示例:
Browser Js
轻量级CDP浏览器控制,适用于AI代理。相较于内置浏览器工具,token消耗降低3‑10倍,仅在浏览时使用。
下载
const list = [
{ id: 1, name: 'Alice', dept: 'HR' },
{ id: 2, name: 'Bob', dept: 'IT' },
{ id: 1, name: 'Alice', dept: 'Finance' }, // id 重复
];
console.log(uniqueByField(list, 'id'));
// → [{ id: 1, name: 'Alice', dept: 'HR' }, { id: 2, name: 'Bob', dept: 'IT' }]
用 reduce + find 实现(兼容性好,逻辑直观)
遍历数组,每次检查结果中是否已有相同字段值的对象;没有就 push 进去。
- 适合需要保留首项、且不依赖 Map 的环境(如旧版浏览器)
- 性能略低于 Map(O(n²)),但数据量不大时无感
const uniqueByField = (arr, field) => {
return arr.reduce((unique, item) => {
const exists = unique.some(obj => obj[field] === item[field]);
return exists ? unique : [...unique, item];
}, []);
};
处理嵌套字段或动态路径(如 user.profile.name)
当去重字段是深层属性(如 user.info.id)时,可用函数安全取值:
const get = (obj, path) => {
return 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 (!map.has(key)) map.set(key, item);
}
return Array.from(map.values());
};
// 使用:uniqueByPath(list, 'user.info.id')
注意事项和常见坑
-
null/undefined 字段值:多个对象该字段为 `null` 或 `undefined` 会被视为同一 key,只留一个——这是预期行为,如需区分,可转成字符串加类型前缀(如
`null_${typeof val}`)
-
字段值非原始类型(如对象、数组):不能直接用作 Map key,需先 JSON.stringify 或生成唯一字符串(慎用,注意顺序和 undefined 处理)
-
大小写敏感:如按 `name` 去重但希望忽略大小写,提前转成
item[field].toLowerCase()