Search code examples
javascriptecmascript-2016

How to combine objects with objects.assign?


My simple code

const ob1 = {
  a: 'pokushevski',
  b: '2001',
};

const obj2 = {
  obj1: {},
  c: '1999',
};

const result = Object.assign(ob1, obj2);
console.log(result);
console.log(Object.getOwnPropertyNames(result));

Output

{ a: 'pokushevski', b: '2001', obj1: {}, c: '1999' }
[ 'a', 'b', 'obj1', 'c' ]

It seems that obj1 in result appears just as any other attribute,without having any reference to const obj1. Why?


Solution

  • What you are doing right now is basically merging ob1 (without 'j') with obj2 (with 'j'), and since obj1 (with 'j') is an empty object inside of obj2, it gets added as a property on the resulting merged object.

    What else did you expect, and can we help in getting you there?

    Maybe you actually made a typo and wanted the first object ob1 to be named obj1 instead, then to be used as a property within obj2 and finally merge the two objects?

    If so you co do:

    const obj1 = {
      a: 'pokushevski',
      b: '2001',
    };
    
    const obj2 = {
      obj1, // shorthand syntax, property will be named the same as the const
      c: '1999',
    };
    
    // avoid mutation by using a new object as the target
    const result = Object.assign({}, obj1, obj2);
    
    // Display result and property names
    console.log(result);
    console.log(Object.getOwnPropertyNames(result));
    

    If you only wanted to add obj1 within obj2 you don't need Object.assign

    Watch out for what's mutable

    With the code above, the original obj1 gets modified whenever you update result.obj1 properties. Try to update result.obj1.a and then console.log(obj1)

    If you want to prevent this, you can use destructuring like so:

    const obj1 = {
      a: 'pokushevski',
      b: '2001',
    };
    
    // Create a shallow copy of `obj1` to prevent mutating the original
    // object by updating `obj2.obj1` properties
    const obj2 = {
      obj1: {...obj1},
      c: '1999',
    };
    
    // Avoid mutating the original `obj1` by using a new object as the target
    const result = Object.assign({}, obj1, obj2);
    
    // Display result and property names
    console.log(result);
    console.log(Object.getOwnPropertyNames(result))
    

    If you really want to keep using Object.assign instead of destructuring you can replace obj1: {...obj1} by obj1: Object.assign({}, obj1)