我有2个不同的嵌套对象,我需要知道它们是否在其中一个嵌套属性中有不同。

var a = {};
var b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

对象可以更复杂,有更多嵌套的属性。但这是一个很好的例子。我可以选择使用递归函数或lodash的东西…


当前回答

这段代码返回一个具有不同值的所有属性的对象,以及两个对象的值。对记录差异很有用。

var allkeys = _.union(_.keys(obj1), _.keys(obj2));
var difference = _.reduce(allkeys, function (result, key) {
  if ( !_.isEqual(obj1[key], obj2[key]) ) {
    result[key] = {obj1: obj1[key], obj2: obj2[key]}
  }
  return result;
}, {});

其他回答

以Sridhar Gudimela的回答为基础,下面以一种使用TypeScript的方式进行了更新:

///  U T I L S

interface LooseObjectInterface {
  [key: string]: any;
};

type inputOptions = LooseObjectInterface | any[];



///  E X P O R T

export const objectCompare = (objectA: inputOptions, objectB: inputOptions): LooseObjectInterface => {
  let diffObj: LooseObjectInterface = {};

  switch(true) {
    case (Array.isArray(objectA)):
      objectA.forEach((elem: any, index: number) => {
        if (!Array.isArray(diffObj))
          diffObj = [];

        diffObj[index] = objectCompare(elem, (objectB || [])[index]);
      });

      break;

    case (objectA !== null && typeof objectA === "object"):
      Object.keys(objectA).forEach((key: any) => {
        if (Array.isArray(objectA[key])) {
          let arr = objectCompare(objectA[key], objectB[key]);

          if (!Array.isArray(arr))
            arr = [];

          arr.forEach((elem: any, index: number) => {
            if (!Array.isArray(diffObj[key]))
              diffObj[key] = [];

            diffObj[key][index] = elem;
          });
        } else if (typeof objectA[key] === "object")
          diffObj[key] = objectCompare(objectA[key], objectB[key]);
        else if (objectA[key] !== (objectB || {})[key])
          diffObj[key] = objectA[key];
        else if (objectA[key] === (objectB || {})[key])
          delete objectA[key];
      });

      break;

    default:
      break;
  }

  Object.keys(diffObj).forEach((key: any) => {
    if (typeof diffObj[key] === "object" && JSON.stringify(diffObj[key]) === "{}")
      delete diffObj[key];
  });

  return diffObj;
};

编辑:我最初的回答使用了Flow,因此被否决了(我猜,或者可能是因为我的回答没有使用Lodash……)然而,有一个类似问题的答案也无妨)。

这段代码返回一个具有不同值的所有属性的对象,以及两个对象的值。对记录差异很有用。

var allkeys = _.union(_.keys(obj1), _.keys(obj2));
var difference = _.reduce(allkeys, function (result, key) {
  if ( !_.isEqual(obj1[key], obj2[key]) ) {
    result[key] = {obj1: obj1[key], obj2: obj2[key]}
  }
  return result;
}, {});

简单使用_。isEqual方法,它将适用于所有比较…

注意:此方法支持比较数组、数组缓冲区、 布尔值、 *日期对象,错误对象,地图,数字,对象对象,正则表达式, *集合、字符串、符号和类型化数组。对象对象进行比较 *通过自身的,不可继承的,可枚举的属性。函数和DOM *节点不支持。

所以如果你有以下情况:

 const firstName = {name: "Alireza"};
 const otherName = {name: "Alireza"};

如果是:_。isEqual (firstName, otherName);

它会返回true

如果const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};

如果是:_。isEqual (firstName, fullName);

将返回false

要递归地显示一个对象与其他对象的不同之处,可以使用_。Reduce与_结合。isEqual和_.isPlainObject。在这种情况下,你可以比较a与b的不同,或者b与a的不同:

const objectA = { a: { 1: "SAME WILL BE MISSING IN RESULT", 2: "BBB", 3: [1, 2, 3] }, b: "not", c: "foo bar" }; const objectB = { a: { 1: "SAME WILL BE MISSING IN RESULT", 2: [1, 2] }, b: "foo", c: "bar" }; const diff = function(obj1, obj2) { return _.reduce(obj1, function(result, value, key) { if (_.isPlainObject(value)) { result[key] = diff(value, obj2[key]); } else if (!_.isEqual(value, obj2[key])) { result[key] = value; } return result; }, {}); }; const diffAOverB = diff(objectA, objectB); const diffBOverA = diff(objectA, objectB); console.log(diffAOverB); console.log(diffBOverA); <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>

我知道这并不能直接回答OP的问题,但我是通过搜索如何删除lodash被引导到这里的。希望这能帮助到和我处境相似的人。

这要归功于@JohanPersson。我在这个答案的基础上实现了对深度嵌套值的比较,并获得对差异的键引用

getObjectDiff = (obj1, obj2) => { const obj1Props = Object.keys(obj1); const obj2Props = Object.keys(obj2); const keysWithDiffValue = obj1Props.reduce((keysWithDiffValueAccumulator, key) => { const propExistsOnObj2 = obj2.hasOwnProperty(key); const hasNestedValue = obj1[key] instanceof Object && obj2[key] instanceof Object; const keyValuePairBetweenBothObjectsIsEqual = obj1[key] === obj2[key]; if (!propExistsOnObj2) { keysWithDiffValueAccumulator.push(key); } else if (hasNestedValue) { const keyIndex = keysWithDiffValueAccumulator.indexOf(key); if (keyIndex >= 0) { keysWithDiffValueAccumulator.splice(keyIndex, 1); } const nestedDiffs = getObjectDiff(obj1[key], obj2[key]); for (let diff of nestedDiffs) { keysWithDiffValueAccumulator.push(`${key}.${diff}`); } } else if (keyValuePairBetweenBothObjectsIsEqual) { const equalValueKeyIndex = keysWithDiffValueAccumulator.indexOf(key); keysWithDiffValueAccumulator.splice(equalValueKeyIndex, 1); } return keysWithDiffValueAccumulator; }, obj2Props); return keysWithDiffValue; } const obj1 = {a0: {a1: {a2: {a3: 'Im here'}}}}; const obj2 = {a0: {a1: {a2: {a3: 'Not here', b3: 'some'}}}}; console.log('final', getObjectDiff(obj1, obj2));