How to do a deep comparison between 2 objects with lodash?
An easy and elegant solution is to use _.isEqual
, which performs a deep comparison:
var a = {};var b = {};a.prop1 = 2;a.prop2 = { prop3: 2 };b.prop1 = 2;b.prop2 = { prop3: 3 };console.log(_.isEqual(a, b)); // returns false if different
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
However, this solution doesn't show which property is different.
If you need to know which properties are different, use reduce():
_.reduce(a, function(result, value, key) { return _.isEqual(value, b[key]) ? result : result.concat(key);}, []);// → [ "prop2" ]
For anyone stumbling upon this thread, here's a more complete solution. It will compare two objects and give you the key of all properties that are either only in object1, only in object2, or are both in object1 and object2 but have different values:
/* * Compare two objects by reducing an array of keys in obj1, having the * keys in obj2 as the intial value of the result. Key points: * * - All keys of obj2 are initially in the result. * * - If the loop finds a key (from obj1, remember) not in obj2, it adds * it to the result. * * - If the loop finds a key that are both in obj1 and obj2, it compares * the value. If it's the same value, the key is removed from the result. */function getObjectDiff(obj1, obj2) { const diff = Object.keys(obj1).reduce((result, key) => { if (!obj2.hasOwnProperty(key)) { result.push(key); } else if (_.isEqual(obj1[key], obj2[key])) { const resultKeyIndex = result.indexOf(key); result.splice(resultKeyIndex, 1); } return result; }, Object.keys(obj2)); return diff;}
Here's an example output:
// Testlet obj1 = { a: 1, b: 2, c: { foo: 1, bar: 2}, d: { baz: 1, bat: 2 }}let obj2 = { b: 2, c: { foo: 1, bar: 'monkey'}, d: { baz: 1, bat: 2 } e: 1}getObjectDiff(obj1, obj2)// ["c", "e", "a"]
If you don't care about nested objects and want to skip lodash, you can substitute the _.isEqual
for a normal value comparison, e.g. obj1[key] === obj2[key]
.