JS对象数组多字段去重核心是构造唯一键:用Map+字符串键(推荐),手动拼接字段值并用\x00分隔;或reduce+findIndex(兼容性好);或Set+JSON.stringify(需注意属性顺序)。

JS 中处理多字段联合相等的对象数组去重,核心是定义“哪些字段组合起来决定对象是否重复”,然后基于该组合生成唯一标识(如字符串或 symbol),再用 Map 或 Set 去重。
用 Map + 字符串键实现(推荐,清晰易懂)
对每个对象提取指定字段,按固定顺序拼成字符串作为 key(注意字段值类型统一,避免 undefined / null 导致误判):
- 先用
JSON.stringify序列化字段数组(简单但注意:属性顺序必须一致,且不支持函数、undefined、Symbol 等) - 更稳妥的方式是手动拼接,对每个字段做
String(val)处理,并用分隔符(如|)隔开,避免字段值含分隔符时冲突(可加转义或用更安全的分隔符如\x00) - 用 Map 缓存已见过的 key,只保留首次出现的对象
示例(去重依据 name 和 age):
const arr = [
{ id: 1, name: 'Alice', age: 30, city: 'Beijing' },
{ id: 2, name: 'Bob', age: 25, city: 'Shanghai' },
{ id: 3, name: 'Alice', age: 30, city: 'Guangzhou' }, // 与第 1 项 name+age 相同,应去重
];
const uniqueByKey = (arr, keys) => {
const seen = new Map();
return arr.filter(item => {
const key = keys.map(k => String(item[k])).join('\x00');
if (seen.has(key)) return false;
seen.set(key, true);
return true;
});
};
uniqueByKey(arr, ['name', 'age']);
// → [{ id: 1, name: 'Alice', age: 30, city: 'Beijing' }, { id: 2, name: 'Bob', age: 25, city: 'Shanghai' }]
用 reduce + findIndex(兼容性好,适合小数据)
不依赖 Map,逐个检查当前项在已选结果中是否已有相同字段组合:
- 遍历原数组,对每一项,在已积累的结果中用
findIndex判断是否存在字段全等的对象 - 比较时用
every检查所有目标字段值是否严格相等(===) - 注意:对
null/undefined要显式处理,避免undefined === undefined成立但业务上不希望它们被当作相同
const uniqueByFields = (arr, fields) => {
return arr.reduce((acc, curr) => {
const exists = acc.find(item =>
fields.every(f => item[f] === curr[f])
);
return exists ? acc : [...acc, curr];
}, []);
};
用 Set + 自定义序列化(适合复杂值或需深度比较)
当字段可能为对象、数组等需要深比较时,可借助 JSON.stringify(前提字段值可序列化且顺序稳定)或引入轻量 deep-equal 逻辑:
- 对每项提取字段并深序列化(例如用
JSON.stringify({name, age})) - 用 Set 存储这些字符串,过滤重复
- ⚠️ 注意:
JSON.stringify({a:1,b:2}) !== JSON.stringify({b:2,a:1}),所以字段提取后建议转为有序对象或数组再序列化
const uniqueByDeepFields = (arr, fields) => {
const seen = new Set();
return arr.filter(item => {
const subset = Object.fromEntries(fields.map(k => [k, item[k]]));
const key = JSON.stringify(subset);
if (seen.has(key)) return false;
seen.add(key);
return true;
});
};
性能与边界提醒
大数据量时注意:
- 避免在循环中频繁调用
JSON.stringify或嵌套find/findIndex(时间复杂度 O(n²)) - 优先用 Map + 字符串 key 方案(O(n))
- 字段值含
undefined时,String(undefined) === 'undefined',若业务中希望忽略该字段,需提前映射为null或空字符串 - 若字段名动态或来自用户输入,记得校验字段是否存在,防止
item[k]报错


















