Make clone of array (not copy of reference) and modify the new array

Viewed 221

I assume my issue is easy to fix but as beeing a newbee I can not get there.

const arr1 = [
  { department: "Lebensmittel", id: "id6", product: "Nudeln", status: false },
  { department: "Ceralien", id: "id5", product: "Marmelade", status: false },
  { department: "Ceralien", id: "id3", product: "Müsli", status: false },
  { department: "Ceralien", id: "id4", product: "Honig", status: false },
  { department: "Molkereiprodukte", id: "id1", product: "Milch", status: false }
];

let testArr = [...arr1];

testArr.forEach(obj => (obj.status = "test"));

console.log(arr1, testArr)

The log shows, that the forEach() functions gets also applied on the arr1. Why is this and how can I keep arr1 unmutable?

arr1 = [
  { department: "Lebensmittel", id: "id6", product: "Nudeln", status: false },
  { department: "Ceralien", id: "id5", product: "Marmelade", status: false },
  { department: "Ceralien", id: "id3", product: "Müsli", status: false },
  { department: "Ceralien", id: "id4", product: "Honig", status: false },
  { department: "Molkereiprodukte", id: "id1", product: "Milch", status: false }
];

 testArr = [
  { department: "Lebensmittel", id: "id6", product: "Nudeln", status: false },
  { department: "Ceralien", id: "id5", product: "Marmelade", status: false },
  { department: "Ceralien", id: "id3", product: "Müsli", status: false },
  { department: "Ceralien", id: "id4", product: "Honig", status: false },
  { department: "Molkereiprodukte", id: "id1", product: "Milch", status: false }
];
5 Answers

arr1 contains objects, so just cloning arr1 is not enough. You need to clone the objects in the arr1 too.

You can use .map() function and the spread operator to create a new array that contains clones of the objects in arr1.

const arr1 = [
  { department: "Lebensmittel", id: "id6", product: "Nudeln", status: false },
  { department: "Ceralien", id: "id5", product: "Marmelade", status: false },
  { department: "Ceralien", id: "id3", product: "Müsli", status: false },
  { department: "Ceralien", id: "id4", product: "Honig", status: false },
  { department: "Molkereiprodukte", id: "id1", product: "Milch", status: false }
];

let testArr = arr1.map(obj => ({...obj}));

testArr.forEach(obj => (obj.status = "test"));

console.log(arr1[0]);
console.log(testArr[0]);
.as-console-wrapper { max-height: 100% !important; top: 0; } 

Using .map() function allows you to update the returned objects as well. So you could remove forEach loop and just use .map() function to not only clone the objects but also update the status property of the cloned object.

const arr1 = [
  { department: "Lebensmittel", id: "id6", product: "Nudeln", status: false },
  { department: "Ceralien", id: "id5", product: "Marmelade", status: false },
  { department: "Ceralien", id: "id3", product: "Müsli", status: false },
  { department: "Ceralien", id: "id4", product: "Honig", status: false },
  { department: "Molkereiprodukte", id: "id1", product: "Milch", status: false }
];

let testArr = arr1.map(obj => ({...obj, status: 'test'}));

console.log(arr1[0]);
console.log(testArr[0]);
.as-console-wrapper { max-height: 100% !important; top: 0; }

In your example the object are byRef. This means that they are not deep copied. You can create a new Array by using map and Object.assign:

const testArr = arr1.map(i => Object.assign({}, i)); 

Then after running:

testArr.forEach(obj => (obj.status = "test"));
console.log(arr1, testArr)

You can see that the arr1 objects where not mutated (screenshot from my console): enter image description here

if you want keep your original data without mutate it you could use map or Object.assign

const arr1 = [ { department: "Lebensmittel", id: "id6", product: "Nudeln", status: false }, { department: "Ceralien", id: "id5", product: "Marmelade", status: false }, { department: "Ceralien", id: "id3", product: "Müsli", status: false }, { department: "Ceralien", id: "id4", product: "Honig", status: false }, { department: "Molkereiprodukte", id: "id1", product: "Milch", status: false } ];
   
const newarray=  arr1.map(o=>({...o,["status"]:"test"}))
 console.log(arr1)
 console.log(newarray)

in javascript, clonedArray=originalArray just creates a reference == the same array.
you can overcome this/"clone" a simple array by:

clonedArray=originalArray.slice()

or, for complex (say, with objects), the "quickest" way is:

clonedArray=JSON.parse(JSON.stringify(originalArray))
Related