5

I have two objects like this:

var a = {prop:{a:'1'}}
var b = {prop:{b:'1'}}

I want to merge the two objects using Object.assign. I tried this:

var c = Object.assign(a,b)
> {prop:{b:'1'}}

How do I get this output:

{prop:{a:'1',b:'1'}}

In short, I want to do Object assign on every sub Objects => (IF PROPERTY EXISTS, CHECK CHILDREN FIRST IF IT AS OBJECT, DO NOT OVERIDE)

3
  • in above code, c === a, because of Object.assign. do you want a new object or assign to a ? Commented Sep 1, 2018 at 20:31
  • I want to merge them in a new object Commented Sep 1, 2018 at 20:32
  • There's no built-in function to recursively merge objects, but you could use merge from Lodash. lodash.com/docs#merge Commented Sep 1, 2018 at 20:37

2 Answers 2

9

You could use a deep merge function for every level of the object.

The function deepMerge works as single function for a given target or as callback for Array#reduce, where an array of objects is iterated and an empty object is supplied as startvalue for reducing.

The function/callback itselft has two parameters, one for the target object and one for the source object where all entries are taken and iterated.

A value of the object is checked and if the type is an object, then a recursive call of deepMerge is done with a a new target property, if not given or to an exitent property.

If the value is not an object, the value is assigned to target with the given key.

The result is a new object with all properties of the given objects.

function deepMerge(target, source) {
    Object.entries(source).forEach(([key, value]) => {
        if (value && typeof value === 'object') {
            deepMerge(target[key] = target[key] || {}, value);
            return;
        }
        target[key] = value;
    });
    return target;
}

var a = { prop: { a: '1' } },
    b = { prop: { b: '1' } },
    c = [a, b].reduce(deepMerge, {});
    
console.log(c);

Sign up to request clarification or add additional context in comments.

3 Comments

Yes. But why? ;)
as i see it, op wants a deep merge of objects. actually js do not supot this out of the box. that's why you need to write an own merger wor arbitrary count of nestings and properties without knowing them in advance.
Could you please add an explanation ? (comments on the algorithm. I see you are using a nested function call)
2

Since a and b in your case contains a property with same name, when you do something like Object.assign(a,b)the prop property of b overwrites and not merge the prop. Reference

Try the following:

var a = {prop:{a:'1'}}
var b = {prop:{b:'1'}}

var c = {};
c.prop = Object.assign({},a.prop,b.prop);

console.log(c);

Or

You can write your own custom function which can merge the values of the objects with same properties.

Try the following:

function merge(source, target) {
    Object.keys(source).forEach((k) => {
        if (source[k].constructor.toString().indexOf('Object') > -1 && target[k]) {          
            merge(source[k], target[k]);
            return;
        }
        target[k] = source[k];
    });
    return target;
}

var a = {prop:{a: '1'}};
var b = {prop:{ b: '1'}};
var c = {};
[a,b].forEach((e)=>merge(e, c));
    
console.log(c);

4 Comments

that works only for a single (and know upper) level.
@NinaScholz op has edited the question just now only :-)
can you add a bit of explanations please?
The first argument is the target, the rest are sources – See: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.