You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:45:43