Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript .push() inside function is overriding global variable

I have the following problem with .push() method:

var myArray = ["a", "b", "c", "d"];

function add(arr) {
    arr.push("e");
    return arr;
}

add(myArray);

// myArray is now  ["a", "b", "c", "d", "e"]

Why it overrides myArray? Can't understand that...

like image 967
Jany Avatar asked Dec 12 '22 19:12

Jany


2 Answers

Arrays in Javascript (and most other languages) are passed by reference.

When you write add(myArray), you are passing a reference to the same Array instance that the global myArray variable refers to.
Any changes to the array object will be visible through both references.

To copy the actual array instance, write add(myArray.slice());.
Note that this will not copy the objects inside of it.

like image 186
SLaks Avatar answered Mar 07 '23 08:03

SLaks


If you need to be able to nest arrays, then I'd change the .add() function to have the .concat() duplicate the Array into a variable, .push() the new value into the new Array, and return it.

function add(arr) {
    var newArr = arr.concat(); // duplicate
    newArr.push("e");      // push new value
    return newArr;         // return new (modified) Array
}

You could use concat() as well, and return the new array it creates.

var myArray = ["a", "b", "c", "d"];

function add(arr) {
    return arr.concat("e");
}
var newArray = add(myArray);

console.log( newArray );  // ["a", "b", "c", "d", "e"]
console.log( myArray );   // ["a", "b", "c", "d"]

So instead of two methods .slice() then .push(), you accomplish it with one .concat().

This also gives you the benefit of passing another Array instead of a string, so:

return arr.concat(["e","f"]);

would give you:

// ["a", "b", "c", "d", "e", "f"]

instead of:

// ["a", "b", "c", "d", ["e", "f"] ]
like image 32
user113716 Avatar answered Mar 07 '23 08:03

user113716