How to Deep Merge Instead of Shallow Merge

Deep and shallow merge in javascript

In a shallow merge, the properties of the first object are overwritten with the same property values of the second object.

Lets look at an example. Setup:

var obj1 = {
foo: {
prop1: 42,
},
};

var obj2 = {
foo: {
prop2: 21,
},
bar: {
prop3: 10,
},
};

Shallow:

var result = {
foo: { // `foo` got overwritten with the value of `obj2`
prop2: 21,
},
bar: {
prop3: 10,
},
};

Deep:

var result = {
foo: {
prop1: 42,
prop2: 21, // `obj2.foo` got merged into `obj1.foo`.
},
bar: {
prop3: 10,
},
};

How can I combine 2 objects and merge arrays inside of them

You are looking for lodash.mergeWith, which merges arrays and plain object properties recursively.

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};
 
var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
};

function customizer(objValue, srcValue) {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
}
 
_.mergeWith(object, other, customizer);
// => { 'a': [{ 'b': 2 }, { 'c': 3 }, { 'd': 4 }, { 'e': 5 }] }

For your particular case when you know the ids of the objects, this customizer function will work as requested.

function customizer(objValue, srcValue) {
  if (_.isArray(objValue)) {
for (const srcItem of srcValue) {
const objItem = objValue.filter(item => item.id === srcItem.id);
if (objItem.length) {
objValue = objValue.map(item => {
if (item.id === objItem[0].id) {
return _.mergeWith(item, srcItem, customizer);
}

return item;
});
} else {
objValue = [...objValue, srcItem];
}
}

    return objValue;
  }
}

Deep merge objects without cloning

So, I implemented it myself and it seems to work just fine.

/**
* Custom merge function with in place merge with behaviour similar to that of _.merge.
*
* @param {object} tar target object in which the other object is to be merged
* @param {object} src source object which is to be merged
* @returns object merged object
*/
function inPlaceMerge(tar, src) {
let res = tar;
if (_.isObject(src) && _.isObject(tar)) {
_.forEach(src, (val, key) => {
res[key] = inPlaceMerge(tar[key], val);
})
} else if (src !== undefined) {
res = src;
}
return res;
}


Related Topics



Leave a reply



Submit