JavaScript Array Cloning: Objects vs Primitives

Written by Andrew Rady
4
This post is days old.

In JavaScript, we are always working with different data types to send to the API or display on the UI. Cloning and altering that clone is a very common thing we do every day. Sometimes we only want to alter the newly cloned data without affecting the original data. For example, we can copy an array and alter the new one and everything works out fine.

let originalArray = [1,2,3,4];
let newArray = originalArray.slice();
newArray.push(5);

console.log(originalArray);
[1,2,3,4]

console.log(newArray);
[1,2,3,4,5]

As you can see, we can alter the newArray and push the integer of 5 in without altering the originalArray. This is nothing new and is covered in basic JavaScript, but there can be a gotcha when we need to clone objects. For this example, we are going to imagine we have an array of objects from the API. We want to display that data and filter it from the UI. The idea is to take input from the user, clone the original array we got from the API, and apply the filters without altering the original array. This is where deep cloning and shallow cloning comes in. Below is the way to “clone” this array.

let clientList = [
  {
    "firstName": "Chuck",
    "lastName": "Norris",
    "address": "1600 Pennsylvania Ave NW",
    "city": "Washington",
    "state": "DC",
    "zip": "20500"
  },
  {
    "firstName": "John",
    "lastName": "Snow",
    "address": "",
    "city": "",
    "state": "",
    "zip": ""
  },
  {
    "firstName": "Mickey",
    "lastName": "Mouse",
    "address": "1313 Disneyland Dr",
    "city": "Anaheim",
    "state": "CA",
    "zip": "92802"
  }
]

Now if we create a new array called filteredList by just assigning it from clientList and alter an object, you will see it reflect in both variables.

let filteredList = clientList.slice();

filteredList[0].firstName= "Billy";

console.log(filteredList);
"Billy"
console.log(clientList);
"Billy"

This is happening because when we created the new array filteredList, we only shallow cloned clientList. Instead of copying the objects into a new array, we only copied a reference back to the original object. If you alter a reference object, it really changes the original object. This can be an issue if we want to keep the integrity of the original API response object.

Easy and simple

An easy way to handle this situation is to use JSON.parse and JSON.stringify.

JSON.stringify works because it turns your entire data structure to a string. Since strings are a primitive value, this removes any references that existed in the object, so when you turn the string back to an array of objects with JSON.parse all references are now gone, leaving you with a deep clone.

let filteredList = JSON.parse(JSON.stringify(clientList));

filteredList[0].firstName= "Billy";

console.log(filteredList);
"Billy"
console.log(clientList);
"Chuck"

This method can help up easily deep clone our objects in arrays and keep the integrity of our original array. I have also included a link to a codepen with some simple examples.

Suggested reading

Comments