javascript复杂对象去重需定义深相等标准,方法一用json.stringify(限规整结构)、方法二手写deepequal(推荐,可控性强)、方法三提取唯一键+map(高效,适合有业务主键),并注意避坑如循环引用和性能问题。

JavaScript 中对包含多层嵌套对象的复杂数据去重,核心在于**定义“重复”的标准**——通常指对象结构完全相同(深相等),而非引用相等。直接用 Set 或 filter() + indexOf() 无效,因为对象无法被原生比较。需结合深比较与唯一标识策略。
方法一:使用 JSON.stringify()(简单场景,有局限)
适用于对象结构规整、不含函数、undefined、Symbol、Date、RegExp、循环引用等“不可序列化”值的情况。
- 将每个对象深转为字符串,再用 Set 去重字符串,最后解析回来
- 注意:属性顺序会影响字符串结果(如
{a:1,b:2}和{b:2,a:1}被视为不同);可先排序键名再序列化来缓解
const data = [{id:1,name:"a",tags:["x"]}, {id:1,name:"a",tags:["x"]}, {id:2,name:"b"}];
const unique = [...new Map(
data.map(item => [JSON.stringify(item), item])
).values()];
方法二:手写深比较 + filter(可控性强,推荐)
适合需要精确控制比较逻辑、处理特殊类型(如 Date、数组、null)、或避免 JSON 序列化副作用的场景。
- 封装一个
deepEqual(a, b)函数,递归比对对象/数组各层级的键、类型和值 - 用
filter()遍历,对每个元素检查它之前是否已存在“深相等”的项
方法三:提取唯一键 + Map 缓存(高效,适合有业务主键)
如果数据中存在天然唯一标识(如 id、uuid,或可组合多个字段生成唯一 key),这是最简洁高效的方式。
- 用
Map以 key 为键、整个对象为值,自动覆盖重复 key - 支持多层嵌套字段提取,例如
item.user.profile.id
const keyFn = item => item.id + '_' + (item.meta?.version || ''); const map = new Map(data.map(item => [keyFn(item), item])); const unique = [...map.values()];
避坑提醒
不要依赖 === 或 == 比较对象;避免在循环中反复深比较导致性能骤降(O(n²));遇到循环引用必须加检测,否则栈溢出;若数据量极大(>1000 条),建议分批处理或引入 Web Worker。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











