2

How would one go about cloning an object that has arrays in it with the new spread operator?

Example Object:

vehicles: { 
  cars:  [1, 2],
  boats: [3, 4]
}

I want a new object with the arrays in it. In that new object I want to be able to change or add to an array without it referencing and effecting vehicles object.

allencoded
  • 7,015
  • 17
  • 72
  • 126

2 Answers2

4

Object.assign and the spread operator create shallow clones, only one level deep, beyond that they are referenced. The best way I've found (Thanks MDN) is to use JSON functions to create a true clone.

let vehicles = { 
  cars:  [1, 2],
  boats: [3, 4],
};

let test = JSON.parse(JSON.stringify(vehicles));

console.log(vehicles, test);

test.cars[0] = 5;
vehicles.cars[0] = 7;

console.log(vehicles, test);
D Lowther
  • 1,609
  • 1
  • 9
  • 16
  • Great solution! – Euroclydon37 Nov 01 '17 at 15:35
  • What if you have large object? Will it handle in that situation? – Sumit Nov 10 '17 at 07:13
  • I don't see why not, if you have a large single level object I would recommend using Object.assign, (personal opinion) I think it is better to use the built in language functions when they will do the job. For large multilevel objects this method will work fine. – D Lowther Nov 13 '17 at 16:56
  • Doesn't seem to work for objects where deeper properties have arrays. The arrays are always blank – Tiago Jul 20 '18 at 17:09
  • I just retested this in the console (chrome 67) with a deeply nested array and object and did not have this issue. Could you paste in your example object, and which os and browser you are using? :) Happy to help debug – D Lowther Jul 20 '18 at 17:27
1

Using JSON.parse(JSON.stringify(object)) to deep copy and object is not the best way if you are looking for performance, rather use a deep copy like this:

let x1 = {
  numbers: {
    number: 1
  }
}
let y1 = copy(x1)
x1.numbers.number++
  console.log(x1)
console.log(y1)

function copy(aObject) { // Deep Clone Object from https://stackoverflow.com/a/34624648/16642626
  if (!aObject) {
    return aObject;
  }

  let v;
  let bObject = Array.isArray(aObject) ? [] : {};
  for (const k in aObject) {
    v = aObject[k];
    bObject[k] = (typeof v === "object") ? copy(v) : v;
  }

  return bObject;
}
Branchverse
  • 1,203
  • 1
  • 7
  • 19