1

I'm setting an array to a property like this:

originalFacilityList: [...maintenanceInfo.Facilities]

However, when I check originalFacilityList downstream, it reflects the updates that were made to the maintenanceInfo.Facilities array. I was thinking that the spread operator was used to break that reference. Am I doing something incorrectly in this example?

iron.man.rball
  • 109
  • 1
  • 5
  • 1
    For a deep copy, you can try `JSON.parse(JSON.stringify(maintenanceInfo.Facilities))` – Unmitigated Aug 09 '21 at 21:10
  • 3
    Does it reflect updates that were made to that array? Or does it reflect updates that were made to **objects inside** that array? – Quentin Aug 09 '21 at 21:10
  • @Quentin - specifically it reflects updates that were made to objects inside that array. for example, if I updated the City of the second Facility from Austin to Dallas, Dallas would be reflected on the facility object of the array that I spread out before the edit facility was updated – iron.man.rball Aug 09 '21 at 21:13
  • 1
    @iron.man.rball — then that's the issue. The spread operator gives you a new array, but it has the same objects in it. It is only a shallow copy. – Quentin Aug 09 '21 at 21:14
  • spread operator only makes a shallow copy, not a deep one. @Unmitigated has given one way to do an arbitrary deep copy, but if those objects don't have nested objects or arrays you could also do `originalFacilityList = maintenanceInfo.Facilities.map(obj => ({...obj}))` – Robin Zigmond Aug 09 '21 at 21:14
  • I generally use https://github.com/immerjs/immer for this sort of problem – Quentin Aug 09 '21 at 21:16
  • Does this answer your question? [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) – pilchard Aug 09 '21 at 21:26

1 Answers1

2

When you do this originalFacilityList: [...maintenanceInfo.Facilities] you are effectively cloning the array. More precisely, you are doing a shallow clone, as opposed to deep clone.

As a result, when you add or remove items from the new array, the changes do not reflect on the original array:

const arr = [1, 2, 3];

const shallowClone = [...arr];

shallowClone.push(4);

console.log(shallowClone, arr);

What you have probably noticed is that the objects contained in the array are actually referenced by the old and the new array:

const arr = [{ property: 'value' }];

const shallowClone = [...arr];

arr[0].newProperty = 'newValue';

console.log(shallowClone);

If you want to avoid that, then you need to deep clone the array. There is no native solution for this, except some solutions like JSON.parse(JSON.stringify( that are very hacky and only work with serializable objects (does not preserve functions, prototypal inheritance, etc...), so either implement it yourself, or use utility libraries like Lodash's cloneDeep.

Guerric P
  • 30,447
  • 6
  • 48
  • 86