递归嵌套对象差异对比函数未返回空对象的修复咨询
修复嵌套对象对比时返回空对象的问题
你的代码存在几个关键问题,导致嵌套对比后出现冗余的空对象结构,以下是问题分析和修复方案:
原代码核心问题
- 笔误:函数参数定义的是
baseObj,但判断逻辑里误用了未定义的refObj;递归调用时写了extractValueChanges,但实际函数名是extractChanges。 - 循环提前返回:遇到第一个非标量类型且值不同的字段就直接
return,会中断后续所有字段的处理。 - 递归结果未过滤:当嵌套对象对比后无差异(返回空对象)时,依然将这个空对象键值对加入结果,导致出现
{address: {coordinates:{}}}这类冗余结构。
修复后的完整代码
function isEmptyValue(value: any): boolean { // 同时处理空对象、空数组的判断 if (Array.isArray(value)) return value.length === 0; if (typeof value === 'object' && value !== null) return Object.keys(value).length === 0; return false; } function extractChanges( baseObj: Record<string, any>, newObj: Record<string, any> ): Record<string, any> { const result: Record<string, any> = {}; // 处理边界情况 if (isEmptyValue(baseObj) && isEmptyValue(newObj)) return result; if (isEmptyValue(baseObj)) return {...newObj}; if (isEmptyValue(newObj)) return result; // 合并两个对象的所有键,避免遗漏baseObj有但newObj删除的字段 const allKeys = new Set([...Object.keys(baseObj), ...Object.keys(newObj)]); for (const key of allKeys) { const baseValue = baseObj[key]; const newValue = newObj[key]; // 判断是否为引用类型(数组/对象) const isBaseRefType = typeof baseValue === 'object' && baseValue !== null; const isNewRefType = typeof newValue === 'object' && newValue !== null; if (isBaseRefType && isNewRefType) { // 递归对比嵌套结构 const nestedChanges = extractChanges(baseValue, newValue); // 仅当递归结果非空时,才加入最终结果 if (!isEmptyValue(nestedChanges)) { result[key] = nestedChanges; } } else if (newValue !== baseValue) { // 非引用类型,值不同则记录差异 result[key] = newValue; } } return result; }
关键修改说明
- 修正笔误:统一将
refObj替换为baseObj,递归调用改为正确的extractChanges。 - 完善空值判断:新增
isEmptyValue函数,同时识别空对象和空数组,避免逻辑误判。 - 合并所有键:用
Set获取两个对象的全部键,确保不会遗漏baseObj存在但newObj删除的字段(可根据需求调整删除字段的处理逻辑)。 - 过滤空递归结果:嵌套对比后若返回空值(无差异),则不将该键加入最终结果,彻底解决冗余空对象问题。
- 移除提前return:循环中不再提前返回,保证所有字段都能被完整处理。
测试验证
对比相同对象时,返回空对象:
const obj = { id: 1, name: 'test', address: { country: 'XXX', state: 'XXXX', coordinates: { longitude: 'xxxx', latitude: 'xxxx', }, }, }; console.log(extractChanges(obj, obj)); // 输出:{}
对比有差异的嵌套对象时,仅返回实际差异:
const modifiedObj = { ...obj, address: { ...obj.address, coordinates: { ...obj.address.coordinates, longitude: 'yyyy', }, }, }; console.log(extractChanges(obj, modifiedObj)); // 输出:{ address: { coordinates: { longitude: 'yyyy' } } }
内容的提问来源于stack exchange,提问作者Slim
相关产品推荐
相关产品推荐

