9

When arrays are assigned to another variable, the reference is passed as opposed to values. This is confirmed when you compare two arrays using == operator and it returns true

var a = [[1,2],[3,4],[5,6]];
var b = a; // b = [[1,2],[3,4],[5,6]]
var c = [].concat(a); // c = [[1,2],[3,4],[5,6]]

a == b; //true
a == c; //false

With the above inputs, when I modify the array b, it mutates array a, but not c.

b.push([7,8]); // b = [[1,2],[3,4],[5,6], [7,8]]
a; //a = [[1,2],[3,4],[5,6], [7,8]]
c; //c = [[1,2],[3,4],[5,6]]

But when I do the below, it mutates c.

b[0].push(5); // b = [[1,2,5],[3,4],[5,6], [7,8]]
a; //a = [[1,2,5],[3,4],[5,6], [7,8]]
c; //c = [[1,2,5],[3,4],[5,6]]

Why does this happen? This behavior happens with the usage of array methods that mutates the array.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Harish
  • 616
  • 6
  • 11

1 Answers1

14

.concat() does a shallow copy. So after the line:

var c = [].concat(a);

c and a reference different arrays, but c[0] and b[0] and a[0] all reference the same array.

Quoting from MDN:

concat copies object references into the new array. Both the original and new array refer to the same object. That is, if a referenced object is modified, the changes are visible to both the new and original arrays.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • +1, that's the answer. Do you think it would be good idea to include how to make *deep* copy of an array (or any other object)? (jQuery `.extend()` or lodash `.deepClone()`?) – bardzusny May 30 '15 at 08:27
  • 1
    @bardzusny there's plenty of answers on stackoverflow already. – Leo May 30 '15 at 08:29
  • thanks nnnnnn, that explains the behavior. As @bardzusny added, could someone suggest any built in methods or libraries that does a deep copy of the arrays? – Harish May 30 '15 at 08:30
  • @Harish - bardzusny already mentioned two libraries that'll do a deep copy. I don't know of a native JS method that does it. Note that you have to be careful with deep copy recursive algorithms because JS allows circular references, so you can have a situation where `x===x[0]` is `true`... – nnnnnn May 30 '15 at 08:32
  • In case my suggestion indeed would mean going out of the scope of the question, here's something that should satisfy you: http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object . Only "vanilla.js" way of easily deep-copying I can think of right off the bat is: `c = JSON.parse(JSON.stringify(a))`, which is not perfect (you lose Date/RegEx/other "special" objects). – bardzusny May 30 '15 at 08:35
  • These links - [this](http://stackoverflow.com/questions/565430/deep-copying-an-array-using-jquery) and [this](http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object) gives more detail for deep copy. I am posting this for the benefit of others. – Harish May 30 '15 at 08:39