values - passing array to function in javascript example




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

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?


A generic solution would be...

// Use the JSON parse to clone the data.
function cloneData(data) {
  // Convert the data into a string first
  var jsonString = JSON.stringify(data);

  //  Parse the string to create a new instance of the data
  return JSON.parse(jsonString);
}

// An array with data
var original = [1, 2, 3, 4];

function mutate(data) {
  // This function changes a value in the array
  data[2] = 4;
}

// Mutate clone
mutate(cloneData(original));

// Mutate original
mutate(original);

This works for objects as well as arrays.

Very effective when you need deep cloning or you don't know what the type is.

Deep cloning example...

var arrayWithObjects = [ { id: 1 }, { id: 2 }, { id: 3 } ];

function mutate(data) {
  // In this case a property of an object is changed!
  data[1].id = 4;
}

// Mutates a (DEEP) cloned version of the array
mutate(cloneData(arrayWithObjects));

console.log(arrayWithObjects[1].id) // ==> 2

Warnings

  • Using the JSON parser to clone is not the most performant option!

  • It doesn't clone functions only JSON supported data types

  • Cannot clone circular references


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.


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);





arrays