Bonio
Bonio

Reputation: 312

Updating an array within a variable created using Object.assign is also updating the original variable

I have created a copy of a variable using Object.assign and I am able to change an array within the copy of the object fine without affecting the original object. However, if I try and update a value within an array on the copied object this is also affecting the original object (i.e. the changes are made to both "job" and "updatedJob").

I have the following code:

  // Create copy of "job" object which has been passed through
  let updatedJob = Object.assign({}, job); 

  // Remove images from updated job object
  updatedJob.Images = null;

  // Remove checklist images from updated job object
  _.each(updatedJob.Checklists, function (checklist) { checklist.Image = null; });

As you can see I have created a copy of the "job" object that has been passed through.

If I then change the "Images" array of the "updateJob" object (to null) this works fine and does not affect the original "job" object (i.e. the original "job" object still has images intact).

However in the last line of the code I am trying to iterate the "Checklists" array witin the "updatedJob" object and change just the "Image" property to "null" for each one but doing this also updates the original "job" object.

How is this possible when the "updatedJob" object should be a copy of the original "job" object therefore any changes I make to it should not affect the original "job" object?

Upvotes: 1

Views: 52

Answers (2)

Jonas Wilms
Jonas Wilms

Reputation: 138267

Object.assign does a shallow copy: It copies all the key-value pairs of one object into another, just like this:

 const from = { primitive: "string", complex: { } }, to = {};

 // Object.assign(from, to) basically does
 to.primitive = from.primitive; // primitives are copied
 to.complex = from.complex; // complex values references get copied, not the value itself

However, objects (arrays are objects too) are copied by reference, so in your case, both objects' Checklists properties point to the same array.

You could create a new array by using .map and reassign the property to point to the new array:

 updatedJob.Checklists = updatedJob.Checklists.map(checklist => ({ ...checklist, Image: null }));

The reference thing here applies here again too, setting .Image to null would affect the object referenced in both arrays, therefore we have to copy these objects too.

Upvotes: 2

Daniel Gimenez
Daniel Gimenez

Reputation: 20504

As stated in comments and other answers, you're doing a shallow copy. Does that _.each() in your code indicate that you're using lodash?

If so, use the deepClone() method so that items are copied recursively:

let updatedJob = _.cloneDeep(job)

Otherwise, there are other questions on SO that deal with this topic that will provide a suitable solution.

Upvotes: 2

Related Questions