React中对比新旧对象生成Patch API差异Payload的实现及Lodash方法
对比新旧对象生成Patch请求Payload的实现方法
我有旧对象(previous)和新对象(new)各一个,需要对比二者的属性差异,将差异属性(保留新对象的值)整理成新对象作为Patch API的请求Payload。需求包括处理嵌套对象和数组的差异,示例如下:
旧对象:
let obj = { Name: "Ajmal", age: 25, email: "ajmaln@gmail.com", contact: [12345678, 987654321], address: { houseName: "ABC", street: "XYZ", pin: 67891 } }
新对象:
let obj2 = { Name: "Ajmal", age: 25, email: "something@gmail.com", contact: [12345678, 11111111], address: { houseName: "ABC", street: "XYZ", pin: 111 } }
期望生成的Payload:
let payload = { email: "something@gmail.com", contact: [12345678, 11111111], address: { pin: 111 } }
一、原生JavaScript递归实现
针对嵌套对象和数组的差异处理,我们可以编写递归函数遍历属性并对比值:
function createPatch(prev, curr) { const patch = {}; Object.keys(curr).forEach(key => { const prevVal = prev[key]; const currVal = curr[key]; // 旧对象无该属性,直接加入patch if (!(key in prev)) { patch[key] = currVal; return; } const isNestedObj = typeof currVal === 'object' && currVal !== null && !Array.isArray(currVal); const isPrevNestedObj = typeof prevVal === 'object' && prevVal !== null && !Array.isArray(prevVal); if (isNestedObj && isPrevNestedObj) { // 递归处理嵌套对象,仅保留有差异的子属性 const nestedPatch = createPatch(prevVal, currVal); if (Object.keys(nestedPatch).length > 0) { patch[key] = nestedPatch; } } else if (Array.isArray(currVal) && Array.isArray(prevVal)) { // 数组直接对比元素是否完全一致,不一致则保留新数组 if (!arraysEqual(prevVal, currVal)) { patch[key] = currVal; } } else { // 基础类型直接对比值 if (prevVal !== currVal) { patch[key] = currVal; } } }); return patch; } // 辅助函数:判断两个数组元素是否完全相等 function arraysEqual(a, b) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; } // 使用示例 const payload = createPatch(obj, obj2); console.log(payload); // 输出:{ email: 'something@gmail.com', contact: [12345678, 11111111], address: { pin: 111 } }
二、使用Lodash实现
Lodash的_.isEqual支持深度对比复杂类型,结合_.transform可以快速构建差异对象:
const _ = require('lodash'); function createPatchWithLodash(prev, curr) { return _.transform(curr, (result, value, key) => { const prevValue = prev[key]; // 深度对比值,不一致则处理 if (!_.isEqual(value, prevValue)) { // 嵌套对象递归处理,非嵌套直接取新值 result[key] = _.isObject(value) && _.isObject(prevValue) ? createPatchWithLodash(prevValue, value) : value; } }, {}); } // 使用示例 const payload = createPatchWithLodash(obj, obj2); console.log(payload); // 输出:{ email: 'something@gmail.com', contact: [12345678, 11111111], address: { pin: 111 } }
说明
_.isEqual会递归对比数组、嵌套对象等所有类型的值,比原生===更全面。_.transform类似对象版的reduce,可以边遍历边构建结果对象。
内容的提问来源于stack exchange,提问作者storm
相关产品推荐
相关产品推荐

