values - passing array to function in javascript example




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

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

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