1

Suppose I made a 5 by 2 matrix populated by integer 9 let arr = Array(5).fill(Array(2).fill(9));

Now I want to push integer 8 into the fourth line of the matrix by doing arr[3].push(8);

I ended up getting [[9,9,8],[9,9,8],[9,9,8],[9,9,8],[9,9,8]]. All lines in the matrix have been pushed 8. Why?

I found out if I did things like below, I got what I wanted, but why?

arr[3] = [...arr[3]];
arr[3].push(8);
Yani
  • 35
  • 4

1 Answers1

1

Short Answer: This is because all 5 arrays are sharing a reference to the exact same array i.e. Array(2).fill(9) => [9,9]

Quick Solution: Use Array.form to create a deep-copy for each layer

let arr = Array.from({length: 5}, e => Array(2).fill(9));

or try any other solution from these answers (ref 1, ref 2, ref 3)

See the working solution below (notice the shallow copy in the console)

// PROBLEM

// Shallow-copies
let arr1 = Array(5).fill([...Array(2).fill(9)]);
arr1[3].push(8);

// writing to the document
document.write('Shallow -> ', arr1)
// loggin in console
console.log('shallow ',  arr1)


// SOLUTION

// deep-copies
let arr2 = Array.from({length: 5}, e => Array(2).fill(9));
arr2[3].push(8);

// writing to the document
document.write('<br><br> Deep -> ', arr2)
// loggin in console
console.log('deep', arr2)

Details: As mentioned in the documentation here (5th point in Description here) about the first parameter of .fill which is the array you are passing in i.e. [9,9]

If the first parameter is an object, each slot in the array will reference that object.

Exact scenario is mentioned inside the documentation as well, see this code snippet here

This shows that all the items are basically a reference to the same object [also known as shallow copy], altering one item will result in the same changes in every other item.

Array.from fixed this issue as Array(2).fill(9) will now create a new array on every element of the array. Learn more about Array.from here


This fix you mentioned at the end is working because by using spread operator [...arr[3]] we are creating a deep copy of this [9,9] array on the 4th index, which is not a reference to that same initial array [9,9] anymore so, now changing this item at 4th index will only change the 4th item's array itself.

Note This spread operator ...arr is only creating a single level deep copy so, if (supposedly) this arr[3] contains another multi-level array inside it, then only the first level will be created as a deep copy and all the inner ones will remain as shallow copies [i.e. same reference to the object]