Object.assign—override nested property

I have an Object a like that:

const a = {
  user: {
   …
   groups: […]
   …
  }
}

whereby there are a lot more properties in a.user

And I would like to change only the a.user.groups value. If I do this:

const b = Object.assign({}, a, {
  user: {
    groups: {}
  }
});

b doesn't have any other Property except b.user.groups, all others are deleted. Is there any ES6 way to only change the nested property, without loosing all the other, with Object.assign?

After some trying I could find a solution that looks pretty nice like that:

const b = Object.assign({}, a, {
  user: {
    ...a.user,
    groups: 'some changed value'
  }
});

To make that answer more complete here a tiny note:

const b = Object.assign({}, a)

is essentially the same as:

const b = { ...a }

since it just copies all the properties of a (...a) to a new Object. So the above can written as:

 const b = {
   ...a,          //copy everything from a
   user: {        //override the user property
      ...a.user,  //same sane: copy the everything from a.user
      groups: 'some changes value'  //override a.user.group
   }
 }

ES6 Object.assign() Sample, assign() which is used to copy the values and properties from one or more source objects to a target object. It invokes getters and setters since it uses both [[Get]]  Object.assign () Method Among the Object constructor methods, there is a method Object.assign () which is used to copy the values and properties from one or more source objects to a target object. It invokes getters and setters since it uses both [ [Get]] on the source and [ [Set]] on the target.

You can change it this way,

const b = Object.assign({}, a, {
  user: Object.assign({}, a.user, {
          groups: {}
        })
});

or just do,

const b = Object.assign({}, a);
b.user.groups = {};

Object.assign( ) in JavaScript, This isn't necessarily exhaustive. Spread syntax. options = {optionsDefault, ​options};. Advantages: If authoring code for execution in environments without  The Object.assign () method is used to copy the values of all enumerable own properties from one or more source objects to a target object. Objects are assigned and copied by reference. It will return the target object.

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

assign method will make a new object by copying from the source object, the issue if you change any method later on in the source object it will not be reflected to the new object.

Use create()

The Object.create() method creates a new object with the specified prototype object and properties.

const b = Object.create(a)
b.user.groups = {}
// if you don't want the prototype link add this
// b.prototype = Object.prototype 

This way you have b linked to a via the prototype and if you make any changes in a it will be reflected in b, and any changes in b will not affect a

Object spread vs. Object.assign, What is the difference between object assign and object create? Object.assign()copies the values (of all enumerable own properties) from one or more source objects to a target object. It has a signature of Object.assign(target,sources). The target object is the first parameter and is also used as the return value. Object.assign()is useful for merging objects or cloning them shallowly.

You asked specifically for an ES6 way with Object.assign, but maybe someone else will prefer my more 'general' answer - you can do it easily with lodash, and personally I think that this solution is more readable.

import * as _ from 'lodash';
_.set(a, 'user.groups', newGroupsValue);

It mutates object.

Object.assign() in JavaScript?, JavaScript Object.assign() copies enumerable and own properties from a source object to a target object. It can be used to clone an object or merge objects. Assigns enumerable own properties of source objects to the target object and returns the target object. Additional source objects will overwrite previous ones.

Here's a small function called Object_assign (just replace the . with a _ if you need nested assigning)

The function sets all target values by either pasting the source value in there directly, or by recursively calling Object_assign again when both the target value and source value are non-null objects.

const target = {
  a: { x: 0 },
  b: { y: { m: 0, n: 1      } },
  c: { z: { i: 0, j: 1      } },
  d: null
}

const source1 = {
  a: {},
  b: { y: {       n: 0      } },
  e: null
}

const source2 = {
  c: { z: {            k: 2 } },
  d: {}
}

function Object_assign (target, ...sources) {
  sources.forEach(source => {
    Object.keys(source).forEach(key => {
      const s_val = source[key]
      const t_val = target[key]
      target[key] = t_val && s_val && typeof t_val === 'object' && typeof s_val === 'object'
                  ? Object_assign(t_val, s_val)
                  : s_val
    })
  })
  return target
}

console.log(Object_assign(Object.create(target), source1, source2))

The Difference Between Object.create and Object.assign, ES2015 Object.assign() ponyfill. Contribute to sindresorhus/object-assign development by creating an account on GitHub. An Object.assign shim. Invoke its "shim" method to shim Object.assign if it is unavailable. This package implements the es-shim API interface. It works in an ES3-supported environment and complies with the spec.

How to deep clone a JavaScript object, Object.assign()This method is used to copy one or more source objects to a target object. It invokes getters and setters since it uses both 'get'  The package is also available as a UMD module (compatible with AMD, CommonJS and exposing a global variable ObjectAssign) in dist/object-assign.js and dist/object-assign.min.js (833 bytes minified and gzipped). The versions with automatic polyfilling are dist/object-assign-auto.js and dist/object-assign-auto.min.js.

object-assign, assign() , the object spread operator does not copy inherited properties or class information. It does copy ES6 symbols. class BaseClass { foo() {  Assigns enumerable own properties of source objects to the target object and returns the target object. Additional source objects will overwrite previous ones.

Using JavaScript Object.assign() Method in ES6, The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. Objects are assigned  For the most part object reset and spread work the same way, the key difference is that spread defines properties, whilst Object.assign () sets them. This means Object.assign () triggers setters. It's worth remembering that other than this, object rest/spread 1:1 maps to Object.assign () and acts differently to array (iterable) spread.

Comments
  • imo it looks to be doing what Object.assign is supposed to. It's changing the user property with the new object you provided. If it's the only thing you want to change why don't you simply do b.user.groups = /* value */?
  • I upvoted because of explaining well and using syntaxic sugar :) Just passing by, if you want to return an array with a new element inside, it's basically the same mechanism : [ ...someArray, newElement ].
  • I must say, exactly what I was looking for and it did the job perfectly.
  • do not mutate b.user.groups, user is shared across b and a!
  • Here's a link to the docs describing what @borovsky mentioned.
  • That is indeed an interesting point, but in this case I need to create a copy of the source.
  • Then your own answer is what you are looking for
  • Or use create() and then do. b.prototype = Object.prototype
  • Well of course, that's why I assumed that you would not like to use my solution but someone else with similar problem might find it useful.