ProgrammingJavascriptCareerProductivityGadgetsASP.NETWeb Design

How to deep clone a JavaScript array

Written by
Published on
Modified on
Filed under
How to deep clone a JavaScript array

If you are looking to make an identical copy of an array in JavaScript, then using the default assignment operator will not do the trick as that will only create a shallow copy.

let arr = [1, 2, 3];

let arr2 = arr;

A shallow copy refers to the fact that while the new variable will contain the values of the original array, it will also actually reference the old array as well, meaning that any changes made to the original array will reflect in the new one. And any changes made in the new one, will reflect in the original as well.

let arr = [1, 2, 3];

let arr2 = arr;

arr.push(4);

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

And that's because using the assignment operator on an array variable does not copy any values from the right side to the left side. It just points the new variable to the original, also known as a reference assignment.

To actually create a brand new array with its own unique values that can be modified independently of another array, you need to create a deep copy (or deep clone). And there are a few ways that you can go about doing that.

for loop

The traditional method of deep cloning an array, is actually kind of tedious. But essentially, you loop through the original array and you push the contents of the original to the new array.

let arr = [1, 2, 3];

let arr2 = [];

for (let i = 0; i < arr.length; i++){
   arr2.push(arr[i]);
}

For static values, such as numbers or strings, this works perfectly fine, though as I mentioned, a bit tedious to type out each time you need to copy an array.

If you are working with an array of objects however, instead of integers or strings, then there is an issue. Object assignments in JavaScript are also treated as shallow copies, meaning that copying one object in an array over to another array, will not create a brand new object.

let obj {a: 'a', b: 'b'};

let arr = [obj];

let arr2 = arr;

console.log(arr2[0]); // {a: 'a', b: 'b'}

In this example above, any changes made to the original object or to the new object will reference the same exact object in memory.

For static values however, this method works just fine.

Destructuring assignment

The simplest method of deep cloning an array in JavaScript as of right now is to use the destructuring assignment syntax introduced in ES6.

let arr = [1, 2, 3];

let [...c] = arr;

console.log(arr); // [1, 2, 3]

console.log(c);   // [1, 2, 3]

The destructuring operator essentially breaks apart a given collection, such as an array, and it assigns those values to a new given variable. Pretty much, it's exactly what we need for this scenario.

In the above example, both the variable c and arr are two completely different variables that can be modified independently.

Note that the destructuring assignment only copies over values to the new array, not references. So if you are working with objects inside of an array, the . . . operator will not deep clone the objects.

So how exactly do you deep clone an array that includes objects?

Cloning an array of objects

If you've noticed from the methods above, the biggest issue with deep cloning an array comes when working with reference values inside of those arrays.

let arr = [{a: 1, b: 2}, {c: 3, d: 4}];

let [...arr2] = arr;

arr[0].b = 10;

console.log(arr2); // [{a: 1, b: 10}, {c: 3, d: 4}];

Destructuring won't work in this case and neither will looping through the array. But there is one more method that you can use that will ensure that a brand new copy is created, given pretty much any kind of data type.

Cloning using JSON

In order to create a brand new (non-referenced) array element, you can convert the target array into a JSON string using the JSON.stringify method and then parse that string back into a JavaScript object using JSON.parse.

let arr = ['a', 'b', 'c'];
let arr2 = JSON.parse(JSON.stringify(arr));

This will generate a true deep-cloned copy of whatever array you are aiming to copy. The one caveat to this method though, is that it is somewhat expensive to run. What do I mean by expensive? I mean that from a performance standpoint, creating an in-memory object from a string takes time. There's no real optimized way for the interpreter to handle this.

Given a simple example like the one mentioned above, there should be no issue with performance. But if you were working with a real-world dataset of thousands of records, then you might encounter issues in performance.

Which method to use?

I think the biggest lesson that I can share here is that there is no one single method to rule them all. The method that you decide to use should be the one that makes the most sense given the scenario that you are in.

If you know for a fact that your dataset contains only static-typed variables, then the destructuring assignment operator will be the fastest way to implement this. If you are serving your website to an audience that is using older browsers that don't support the . . . operator, then perhaps the for loop method might make the most sense.

And if you have reference variables inside of your given array and you need a truly deep-cloned copy, then the JSON conversion method will be your best bet.

As with all things code, there typically isn't any one right answer to things.

Walter Guevara is a software engineer, startup founder and currently teaches programming for a coding bootcamp. He is currently building things that don't yet exist.

Comments

No messages posted yet

Developer Poll

Q:

Stay up to date

Sign up for my FREE newsletter. Get informed of the latest happenings in the programming world.

Add a comment

Keep me up to date on the latest programming news
Add Comment

Stay up to date

Get informed of the latest happenings in the programming world.

No thanks