'js - When pushing an array A into a multidimensional array B, it is overwriting the previous array already on A

Here's an example from the browser console

a=[[1,2,3],[3,2,1]]
b=[]
b.push(a)
a[0][0]=9
b.push(a)

In that case, I was expecting b to be

[[[1,2,3],[3,2,1]],[[9,2,3],[3,2,1]]]

But it will be

[[[9,2,3],[3,2,1]],[[9,2,3],[3,2,1]]]

I'm attaching a screenshot to better show the results in the browser: browsers console with the same code as above and output

Any ideas on why this is happening and how to get to my expecting results?



Solution 1:[1]

Ok, based on all the comments here, specially @code 's one, and also another post (How do I pass the value instead of the reference of an array?) I was able to achieve the results by using this:

b.push([]); 
for(line of a){ 
    b[b.length-1].push(a.slice(0)); 
}

EDIT

Abhijeet's suggestion also works flawlessly:

b.push(a.map(x=>[...x]));

Solution 2:[2]

In JavaScript, objects are passed by reference, meaning "copies" of it aren't copies. They point to the same address in RAM, so mutating one reference mutates 'em all.

To apply to this case, if you didn't already know, arrays are special types of objects. To prove this you can run typeof [] in your browser console. That means that arrays inherit the "pass-by-reference" behavior, meaning if you do let c = a then run c[0] = 1, a will be changed as well and vice versa.

To solve this issue you can use Array.prototype.slice:

const a = [[1, 2, 3], [3, 2, 1]];
const b = [];

Array.prototype.pushWithoutReference = function(add) {
  for(let i = 0; i < add.length; i++) {
    this[this.length] = add[i].slice(0);
  }
}

b.pushWithoutReference(a);
a[0][0] = 9;
b.pushWithoutReference(a);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2