Normally to shallow copy objects I would use angular.extend()
Here's an example of that:
var object1 = { "key": "abc123def456", "message": { "subject": "Has a Question", "from": "[email protected]", "to": "[email protected]" } }; var object2 = { "key": "00700916391" }; console.log(angular.extend({}, object1, object2));
Would give us:
{ "key": "00700916391", "message": { "subject": "Has a Question", "from": "[email protected]", "to": "[email protected]" } }
But what if I wanted to merge objects so that parent keys are not over written by child objects:
var object1 = { "key": "abc123def456", "message": { "subject": "Has a Question", "from": "[email protected]", "to": "[email protected]" } }; var object2 = { "key": "00700916391", //Overwrite me "message": { //Dont overwrite me! "subject": "Hey what's up?", //Overwrite me "something": "something new" //Add me } }; console.log(merge(object1, object2));
Would give us:
{ "key": "00700916391", "message": { "subject": "Hey what's up?", "from": "[email protected]", "to": "[email protected]", "something": "something new" } }
Is there an Angular function that already does a deep merge that I am not aware of?
If not is there a native way to do this in javascript recursively for n levels deep?
You can specify multiple src objects. If you want to preserve original objects, you can do so by passing an empty object as the target: var object = angular. merge({}, object1, object2) .
Deep merging ensures that all levels of the objects we merge into another object are copied instead of referencing the original objects.
Use the spread syntax (...) to merge objects in TypeScript, e.g. const obj3 = { ... obj1, ... obj2 } . The type of the final object will successfully be inferred, so trying to add or remove properties from it will cause the type checker to show an error.
Angular 1.4 or later
Use angular.merge
:
Unlike
extend()
,merge()
recursively descends into object properties of source objects, performing a deep copy.
angular.merge(object1, object2); // merge object 2 into object 1
Older versions of Angular:
There is no reason a simple recursive algorithm shouldn't work :)
Assuming they're both the result of JSON.stringify or similar:
function merge(obj1,obj2){ // Our merge function var result = {}; // return result for(var i in obj1){ // for every property in obj1 if((i in obj2) && (typeof obj1[i] === "object") && (i !== null)){ result[i] = merge(obj1[i],obj2[i]); // if it's an object, merge }else{ result[i] = obj1[i]; // add it to result } } for(i in obj2){ // add the remaining properties from object 2 if(i in result){ //conflict continue; } result[i] = obj2[i]; } return result; }
(Note, arrays are not handled here)
In the new version of Angularjs they added merge function which will perform the deep copy.
For the older versions, I have created my custom function by copying the code of merge function from new version of Angularjs. Below is the code for the same,
function merge(dst){ var slice = [].slice; var isArray = Array.isArray; function baseExtend(dst, objs, deep) { for (var i = 0, ii = objs.length; i < ii; ++i) { var obj = objs[i]; if (!angular.isObject(obj) && !angular.isFunction(obj)) continue; var keys = Object.keys(obj); for (var j = 0, jj = keys.length; j < jj; j++) { var key = keys[j]; var src = obj[key]; if (deep && angular.isObject(src)) { if (!angular.isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; baseExtend(dst[key], [src], true); } else { dst[key] = src; } } } return dst; } return baseExtend(dst, slice.call(arguments, 1), true); }
Hope this will help someone who is wondering why angular.merge is not working in older versions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With