Javascript passing arrays to functions by value, leaving original array unaltered

I've read many answers here relating to 'by value' and 'by reference' passing for sending arrays to javascript functions. I am however having a problem sending an array to a function and leaving the original array unaltered. This example llustrates the problem:

function myFunction(someArray)
{
// any function that makes an array based on a passed array;
// someArray has two dimensions;
// I've tried copying the passed array to a new array like this (I've also used 'someArray' directly in the code);

funcArray = new Array();
funcArray = someArray;

var i = 0;

    for(i=0; i<funcArray.length; i++)
    {
    funcArray[i].reverse;
    }

return funcArray;

}

I can't understand why anything in this function should alter the original array.

calling this function directly changes the original array if the function call is assigned to a new array:

myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];
anotherArray = new Array();

anotherArray = myFunction(myArray);
// myArray gets modified!;

I tried using .valueOf() to send the primitive:

anotherArray = myFunction(myArray.valueOf());
// myArray gets modified!;

I have even tried breaking the array down element by element and sub-element by sub-element and assigning all to a new 2-d array and the original array still gets modified.

I have also joined the sub-elements to a string, processed them, split them back into arrays and the original array still gets modified.

Please, does any one know how I can pass the array values to a function and not have the passed array change?


Inside your function there's this:

funcArray = new Array();
funcArray = someArray;

This won't actually copy someArray but instead reference it, which is why the original array is modified.

You can use Array.slice() to create a so-called shallow copy of the array.

var funcArray = someArray.slice(0);

The original array will be unaltered, but each of its elements would still reference their corresponding entries in the original array. For "deep cloning" you need to do this recursively; the most efficient way is discussed in the following question:

What is the most efficient way to deep clone an object in JavaScript?

Btw, I've added var before funcArray. Doing so makes it local to the function instead of being a global variable.


Make a copy of the array that you can use.

A simple way to do this is by using var clone = original.slice(0);


What about destructuring assignment (ES6+, check compatibility)? Nice and clean solution.

function myFunction(someArray) {

  for(let i = 0; i < someArray.length; i++)
  {
    someArray[i].reverse();
  }
  
  return someArray;
}

let myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];

// Using destructuring assignment.
// NOTE: We can't just use `[...myArray]` because nested arrays will still be copied by reference.
let anotherArray = myFunction([...myArray.map(nested => [...nested])]);

console.log({original: myArray, copy: anotherArray});

With ES6, you can use the spread syntax and destructuring to perform a shallow copy directly in the argument list, allowing you to keep the original array unaltered.

See example below:

const arr = [1, 2, 3, 4, 5];

function timesTen([...arr]) { // [...arr] shallow copy the array
  for(let i = 0; i < arr.length; i++) {
    arr[i] *= 10; // this would usually change the reference
  }
  return arr;
}

console.log(timesTen(arr));
console.log(arr); // unaltered

A variable pointing to an array is a reference to it. When you pass an array, you're copying this reference.

You can make a shallow copy with slice(). If you want a full depth copy, then recurse in sub objects, keeping in mind the caveats when copying some objects.