Why does changing an Array in JavaScript affect copies of the array?

Viewed 78625

I've written the following JavaScript:

var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']

var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4        

This code declares a variable myArray and sets it to an array value. It then declares a second variable copyOfMyArray and sets it to myArray. It performs an operation on copyOfMyArray and then alerts both myArray and copyOfMyArray. Somehow, when I perform an operation on copyOfMyArray, it appears that the same operation is performed on myArray.

The code then does the same thing with a number value: It declares a variable myNumber and sets it to a number value. It then declares a second variable copyOfMyNumber and sets it to myNumber. It performs an operation on copyOfMyNumber and then alerts both myNumber and copyOfMyNumber. Here, I get the expected behavior: different values for myNumber and copyOfMyNumber.

What is the difference between an array and a number in JavaScript that it seems changing an array changes the value of a copy of the array, where as changing a number does not change the value of a copy of the number?

I'm guessing that for some reason, the array is referred to by reference and the number by value, but why? How can I know what behavior to expect with other objects?

12 Answers

The issue with shallow copy is that all the objects aren't cloned, instead it get reference.So array.slice(0) will work fine only with literal array, but it will not do shallow copy with object array. In that case one way is..

var firstArray = [{name: 'foo', id: 121}, {name: 'zoo', id: 321}];
var clonedArray = firstArray.map((_arrayElement) => Object.assign({}, _arrayElement));  
console.log(clonedArray);
// [{name: 'foo', id: 121}, {name: 'zoo', id: 321}]  // shallow copy

For Arrays with objects you can change the use JSON.parse and JSON.strinigfy to change the type of the array to an object refrence to a string and then back to a array without having to worry about the original array

var array = [{name:'John', age:34, logs:'[]'}, {name:'David', age:43, logs:'[3]'}];
  var array2 = JSON.parse(JSON.stringify(array)); // turn object to function output
  array2[0].age++;
  alert(JSON.stringify(array));
  alert(JSON.stringify(array2));
Related