JavaScript Arrays: Value vs Reference

Perhaps you have noticed that if you assign an array to another variable and modify that variable's array elements, the original array is also modified. Or perhaps you have passed an array to a function hoping to modify only the local copy of the array, but you find that the original array has also been modified. This happens because arrays are reference types in JavaScript.

That means that if you assign an array to a variable or pass an array to a function, it is the reference to the original array that is copied or passed, not the value of the array.

Let's demonstrate. Here we declare an array, assign it to a second variable, then modify an array element of the second variable. Notice the output of console.log for the two array variables. Our modification of the second array also modified the first.

var ar = ['one', 'two', 'three'];
var ar2 = ar; // assign ar to ar2

ar2[1] = 2; // modify element in ar2

// change to ar2 also changes ar
console.log( ar ); // ["one", 2, "three"]
console.log( ar2 ); // ["one", 2, "three"]

alert( ar === ar2 ); // true (ar and ar2 refer to the same object)

How to Copy the Value of an Array

You can use either the slice or concat method to make a copy of an array. Then, if the array elements all hold primitive values, you can modify the copy without affecting the original array, as shown here:

var ar = ['one', 'two', 'three'];

var ar2 = ar.slice(0); // assign copy of ar to ar2
//var ar2 = ar.concat(); // concat can also be used to copy

alert( ar === ar2 ); // false (ar and ar2 are not the same object)

ar2[1] = 2; // modify element in ar2

// change to ar2 does not affect ar
console.log( ar ); // ["one", "two", "three"]
console.log( ar2 ); // ["one", 2, "three"]

Notice the alerts in the two code examples.

alert( ar === ar2 );

We test whether the two arrays are identical and find when we simply assign the array to a new variable, the result is true: they are identical. When we use concat or slice to copy the array, the result is false. Even though the two arrays in the second example hold the same elements in the same order, they are not identical since they refer to two separate array objects.

Copy Array of Arrays by Value

If you apply the slice or (concat) method to an array whose elements are themselves arrays, the sub-arrays are copied by reference. So changes to sub-array elements in the copy propagate to the original, as shown here:

var ar = [
    ['apple', 'orange', 'pear'],
    ['carrots', 'beans', 'peas'],
    ['cookies', 'cake', 'muffins', 'pie']
];

//var ar2 = ar.slice(); // use slice or concat to copy
var ar2 = ar.concat(); 

// modify value in sub-array
ar2[1][1] = 'cabbage';
// view original (also modified!)
console.log( ar[1] ); // [ "carrots", "cabbage", "peas" ]

We can use a for loop to iterate through the elements of the outer array and apply the slice method to the sub-arrays to copy each of them by value:

var ar = [
    ['apple', 'orange', 'pear'],
    ['carrots', 'beans', 'peas'],
    ['cookies', 'cake', 'muffins', 'pie']
];

var ar2 = []; // create empty array to hold copy
// for loop to apply slice to sub-arrays
for (var i = 0, len = ar.length; i < len; i++) {
    ar2[i] = ar[i].slice();
}

// modify value in sub-array
ar2[1][1] = 'cabbage';
// view original (not modified)
console.log( ar[1] ); // [ "carrots", "beans", "peas" ]
// view copy with modification
console.log( ar2[1] ); // [ "carrots", "cabbage", "peas" ]

Copy Array of Objects by Value

If you apply the slice method to an array whose elements contain objects, those objects are copied by reference. If you change a property of one of those objects in the copy, it will also be reflected in the original, as shown here:

var arObj = [
    { 'name': 'Jon',  'age': 24 },
    { 'name': 'Mark', 'age': 32 },
    { 'name': 'Kacy', 'age': 22 }
];

// use splice to copy array of objects into second variable
var ar2 = arObj.slice();
// modify property value in copy
ar2[1].name = 'Bill';
// view original (also modified)
console.log( arObj[1].name ); // Bill

We can use a for loop to iterate through the elements of the array, and a nested for-in loop to copy the properties of each object:

var arObj = [
    { 'name': 'Jon',  'age': 24 },
    { 'name': 'Mark', 'age': 32 },
    { 'name': 'Kacy', 'age': 22 }
];

var ar2 = []; // create empty array to hold copy

for (var i = 0, len = arObj.length; i < len; i++) {
    ar2[i] = {}; // empty object to hold properties added below
    for (var prop in arObj[i]) {
        ar2[i][prop] = arObj[i][prop]; // copy properties from arObj to ar2
    }
}

// modify property value in copy
ar2[1].name = 'Mike';
// view property value in original (unchanged)
console.log( arObj[1].name ); // Mark

Back to top