如何便捷且通用地比较包含列表的同类型Object?
判断新旧对象差异的实现方案
你需要对比两个同类型的新旧对象是否存在差异,给定的对象结构示例如下(标准JSON格式):
{ "id": "A524", "name": "test", "data": [ { "id": 0, "name": "test1", "data": [1,2,3] }, { "id": 1, "name": "test2", "data": [1,2] }, { "id": 2, "name": "test3", "data": [2,3] } ] }
由于对象存在嵌套的数组和子对象,直接用===只能判断引用是否相同,无法对比深层内容,这里提供两种递归对比的实现思路:
1. 有序数组场景下的全量对比
如果数组元素的顺序固定(顺序变化也算差异),可以用下面的递归函数遍历所有属性逐一对比:
function isObjectEqual(obj1, obj2) { // 先判断类型是否一致 if (typeof obj1 !== typeof obj2) return false; // 基本类型直接比较值 if (typeof obj1 !== 'object' || obj1 === null) { return obj1 === obj2; } // 数组处理:先比长度,再逐个递归对比 if (Array.isArray(obj1)) { if (obj1.length !== obj2.length) return false; for (let i = 0; i < obj1.length; i++) { if (!isObjectEqual(obj1[i], obj2[i])) { return false; } } return true; } // 对象处理:先比键的数量,再逐个键递归对比值 const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if (keys1.length !== keys2.length) return false; for (const key of keys1) { if (!keys2.includes(key) || !isObjectEqual(obj1[key], obj2[key])) { return false; } } return true; }
用法很简单:
// 若返回true则说明有差异 const hasDifference = !isObjectEqual(oldObject, newObject);
2. 无序数组场景下的匹配对比
如果数组元素的顺序变化不算差异(只要子对象内容一致就认为没变化),可以基于子对象的唯一标识(比如示例中的id)先做映射,再对比内容:
function isObjectEqual(obj1, obj2) { if (typeof obj1 !== typeof obj2) return false; if (typeof obj1 !== 'object' || obj1 === null) { return obj1 === obj2; } if (Array.isArray(obj1)) { if (obj1.length !== obj2.length) return false; // 把数组转成以id为键的对象,方便匹配 const map1 = obj1.reduce((acc, item) => { acc[item.id] = item; return acc; }, {}); const map2 = obj2.reduce((acc, item) => { acc[item.id] = item; return acc; }, {}); // 遍历所有id对应的子对象做对比 for (const id of Object.keys(map1)) { if (!map2[id] || !isObjectEqual(map1[id], map2[id])) { return false; } } return true; } const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if (keys1.length !== keys2.length) return false; for (const key of keys1) { if (!keys2.includes(key) || !isObjectEqual(obj1[key], obj2[key])) { return false; } } return true; }
这两种方案都能覆盖你给出的对象结构,根据实际业务场景选择即可。
内容的提问来源于stack exchange,提问作者JPromi
相关产品推荐
相关产品推荐

