Search code examples
javascriptecmascript-6ecmascript-2016

Javascript: Modifying nested object in ES6 shorthand


Consider a function returns an nested object and I want to modify the property inside the nested object.

In the below example, I'm calling the function many times or I need to store it in a temporary variable. Is there a way to invoke only once inside the braces and spread/modify inside the same object many times.

const getObject = () => {
   return {
     a: {
      b: {
        c: 1,
        d: 2,
      }
     },
     e: 3
   }
}

var modifiedD = {
  ...getObject(),
  a: {
     b: {
      ...getObject().a.b,
      d: 4
     }
  }
}

console.log(modifiedD);


Solution

  • when declaring a key after ...getObject() it replace the whole value. It does not merge the inner object behind a.

    So you could do it as you have done and call getObject() multiple time.


    An other solution could be to handle it using a function of your own merging the objects, like :

    function mergeObjects(obj1, obj2) {
      // We are going to copy the value of each obj2 key into obj1
      Object.keys(obj2).forEach((x) => {
        // If we have an object, we go deeper
        if (typeof obj2[x] === 'object') {
          if (obj1[x] === void 0) {
            obj1[x] = {};
          }
    
          mergeObjects(obj1[x], obj2[x]);
        } else {
          obj1[x] = obj2[x];
        }
      });
      
      return obj1;
    }
    
    const getObject = () => {
      return {
        a: {
          b: {
            c: 1,
            d: 2,
          }
        },
        e: 3
      }
    }
    
    const modifiedD = mergeObjects(getObject(), {
      a: {
        b: {
          d: 4,
        },
      },
    });
    
    console.log(modifiedD);

    WARNING, the function I have made mutate the object which may not be the best answer


    Or call it only once and then set the keys one by one like :

    const getObject = () => {
       return {
         a: {
          b: {
            c: 1,
            d: 2,
          }
         },
         e: 3
       }
    }
    
    const modifiedD = getObject();
    
    modifiedD.a.b.d = 4;
    
    console.log(modifiedD);