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

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

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

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

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


当前回答

我尝试了Adam Boduch的代码来输出一个很深的差异-这完全没有经过测试,但碎片在那里:

function diff (obj1, obj2, path) {
    obj1 = obj1 || {};
    obj2 = obj2 || {};

    return _.reduce(obj1, function(result, value, key) {
        var p = path ? path + '.' + key : key;
        if (_.isObject(value)) {
            var d = diff(value, obj2[key], p);
            return d.length ? result.concat(d) : result;
        }
        return _.isEqual(value, obj2[key]) ? result : result.concat(p);
    }, []);
}

diff({ foo: 'lol', bar: { baz: true }}, {}) // returns ["foo", "bar.baz"]

其他回答

如果你需要知道哪些属性是不同的,使用reduce():

_.reduce(a, function(result, value, key) {
    return _.isEqual(value, b[key]) ?
        result : result.concat(key);
}, []);
// → [ "prop2" ]

已经有很多答案发布,但对于那些好奇的人来说,避免编写任何代码来计算具有任何类型结构的两个对象之间的差异,实际上有一个库可以做到这一点。Lodash isEqual只返回true或false,它不返回任何关于更改属性的信息。https://www.npmjs.com/package/deep-diff

它返回两个对象之间差异的完整细节

import DeepDiff from 'deep-diff';
let a = {...} //some object
let b = {...} //some object 
var differences = DeepDiff.diff(a, b);

在这篇文章中也有人提出了类似的问题 获取2个JSON对象之间的差异

我尝试了Adam Boduch的代码来输出一个很深的差异-这完全没有经过测试,但碎片在那里:

function diff (obj1, obj2, path) {
    obj1 = obj1 || {};
    obj2 = obj2 || {};

    return _.reduce(obj1, function(result, value, key) {
        var p = path ? path + '.' + key : key;
        if (_.isObject(value)) {
            var d = diff(value, obj2[key], p);
            return d.length ? result.concat(d) : result;
        }
        return _.isEqual(value, obj2[key]) ? result : result.concat(p);
    }, []);
}

diff({ foo: 'lol', bar: { baz: true }}, {}) // returns ["foo", "bar.baz"]

我知道这并不能直接回答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));

深度比较使用模板的(嵌套)属性进行检查

function objetcsDeepEqualByTemplate(objectA, objectB, comparisonTemplate) {
  if (!objectA || !objectB) return false

  let areDifferent = false
  Object.keys(comparisonTemplate).some((key) => {
    if (typeof comparisonTemplate[key] === 'object') {
      areDifferent = !objetcsDeepEqualByTemplate(objectA[key], objectB[key], comparisonTemplate[key])
      return areDifferent
    } else if (comparisonTemplate[key] === true) {
      areDifferent = objectA[key] !== objectB[key]
      return areDifferent
    } else {
      return false
    }
  })

  return !areDifferent
}

const objA = { 
  a: 1,
  b: {
    a: 21,
    b: 22,
  },
  c: 3,
}

const objB = { 
  a: 1,
  b: {
    a: 21,
    b: 25,
  },
  c: true,
}

// template tells which props to compare
const comparisonTemplateA = {
  a: true,
  b: {
    a: true
  }
}
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateA)
// returns true

const comparisonTemplateB = {
  a: true,
  c: true
}
// returns false
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateB)

这将在控制台中工作。如果需要,可以添加数组支持