1
var alph = ["a", "b", "c"];
var r = [];

for(var i = 0; i < 5; i += 1) {
    r.push(alph);
}

r[0].reverse();
console.log(r); 

/* Output

[ [ 'c', 'b', 'a' ],
  [ 'c', 'b', 'a' ],
  [ 'c', 'b', 'a' ],
  [ 'c', 'b', 'a' ],
  [ 'c', 'b', 'a' ] ]

*/

/* Expected output

[ [ 'c', 'b', 'a' ],
  [ 'a', 'b', 'c' ],
  [ 'a', 'b', 'c' ],
  [ 'a', 'b', 'c' ],
  [ 'a', 'b', 'c' ] ] 

*/

There are arrays in an array. The first array should be reversed. I thought r[0].reverse() would do this, but instead this reverses all arrays.

Can someone explain why this happens ?

Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
  • The effect isn't localized to `reverse`. You could do `r[0][3] = "d"` and it would similarly change "all of the arrays" at once. It's actually just one array. – 4castle Jun 16 '16 at 13:48
  • objects are reference types in JS. You need to clone the arrays. – Redu Jun 16 '16 at 13:58

3 Answers3

7

You are pushing the reference of the array, so updating one will make changes to the rest since it's all are referring single array. Instead push the copy of the original array for copying array use Array#slice method.

var alph = ["a", "b", "c"];
var r = [];

for (var i = 0; i < 5; i += 1) {
  // push the exact copy of original array
  r.push(alph.slice());
}

r[0].reverse();
console.log(r);
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
4

You're not creating an array of new arrays when you push onto r: you're pushing the same array onto r 5 times (it's being passed by reference, not by value). Therefore, any operation on r[0] is really updating alph, which causes all of the other references to be updated, too.

ajm
  • 19,795
  • 3
  • 32
  • 37
0

Well actually you can use slice method like @Pranav C Balan suggested but this will fail when the array is multidimensional. You need something like Array.prototype.clone() to secure the functionality. Lets do it.

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

var alph = [ 1, 2, 3, 4, [ 1, 2, [ 1, 2, 3 ], 4 ], 5 ],
  cloned = [],
  sliced = [];
for(var i = 0; i < 5; i += 1) {
    cloned.push(alph.clone());
    sliced.push(alph.slice());
}

cloned[0][4][2].reverse(); // only the array at index pos 0,4,2 gets reversed
sliced[0][4][2].reverse(); // all sub arrays at index 4,2 get reversed
console.log(JSON.stringify(cloned));
console.log(JSON.stringify(sliced));
Redu
  • 25,060
  • 6
  • 56
  • 76