3

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 }
];
2
  • ecosia.org/search?tt=mzl2&q=js+clone+array Commented Jul 12, 2020 at 13:10
  • 1
    You are confusing the outer array with making copies of the objects inside them also. [...arr1] only makes a shallow copy, the objects inside are not copied so references are the same between the two arrays Commented Jul 12, 2020 at 13:13

5 Answers 5

6

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; }

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

0

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)

10 Comments

Your map simply returns the same object reference. That is not a deep copy. You can see it in the status properties of your two logs...they are the same in both arrays
@ charlietfl Thank you for the feedback It's fixed now
ok... just an FYI now, you don't need both destructuring and Object.assign. You are basically making two new objects using both
can you elaborate on that more please
Yeah true it's one of them bad habits when writing a code in js that is fixed, hopefully it's the last issue in this tiny code lol
|
-2

Another suggestion is third party package lodash to do a deepcopy (removes references) - https://lodash.com/docs/4.17.15#cloneDeep

2 Comments

It's a matter of preference - I try to use pure javascript.
Link only answers are not very valuable and are frowned on. The link should only be used to support what actually exists in the question itself. Providing lodash code that makes the deep copy while maintaining link to the docs would be the proper way to use this solution in your answer
-2

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))

5 Comments

The arrays contain objects, and .slice() will not clone those.
And the [... arr1] code in the OP basically does the same thing
@Pointy, thank you. When I need a "quick fix" I just use JSON. OP said [...arr1] didn't work..
Another down-voter... Well, it's a correct answer. Just up-vote what you think is better. That's kindness.
the problem is that your first solution will have exactly the same problem that the OP is asking here, and for exactly the same reason. Cloning with the JSON API can work in many cases, but there are object graphs that cannot be serialized successfully (consider object properties with Date or function values).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.