Code Synopsis logo

How to Clone an Array in JavaScript

By default, when you assign an array to a new variable JavaScript does not duplicate the data. Instead, it duplicates a pointer to the same array. Therefore, it’s easy to accidentally mutate the original array.

const inventory1 = ['a', 'b', 'c']; const inventory2 = inventory1; inventory2[3] = 'd'; console.log(inventory1); console.log(inventory2); // both log: ['a', 'b', 'c', 'd'];

You might be wondering how to clone an array to avoid mutation.

An easy way to perform a shallow clone is to use a loop, such as for or while. A shallow clone will duplicate the top level data, but a nested object or array is passed by reference:

const inventory1 = ['a', 'b', 'c']; const inventory2 = []; while (i < inventory1.length) { inventory2.push(inventory1[i]); i++; } inventory2[3] = 'd'; console.log(inventory1); // ['a', 'b', 'c']; console.log(inventory2); // ['a', 'b', 'c', 'd'];

JavaScript ES6 introduced the spread operator [...array]. As above, it is a shallow clone, which is OK as long as the source object doesn’t contain a nested object or array:

const inventory1 = ['a', 'b', 'c']; const inventory2 = [...inventory1]; inventory2[3] = 'd'; console.log(inventory1); // ['a', 'b', 'c']; console.log(inventory2); // ['a', 'b', 'c', 'd'];

However, arrays can contain other arrays or objects. Since the spread operator only clones the top level of data, a nested object would not be duplicated. Instead, a reference to the nested object is copied, which leaves the source object susceptible to mutation.

In the next example, the nested array of numbers is mutated by the change to inventory2. Both variables will show the same values because they are pointing to the same Array object:

const inventory1 = ['a', 'b', 'c', [1, 2, 3]]; const inventory2 = [...inventory1]; inventory2[3].push(4); console.log(inventory1); // ['a', 'b', 'c', [1, 2, 3, 4]]; console.log(inventory2); // ['a', 'b', 'c', [1, 2, 3, 4]];

For a deep clone of an array, you can use the JSON.stringify method to convert the object to a string, and then use JSON.parse to convert it back into an object. Now you have duplicated the data, including all nested objects. A change to anything in one will not affect the other:

const inventory1 = ['a', 'b', 'c', [1, 2, 3]]; const inventory2 = JSON.parse(JSON.stringify(inventory1)); inventory2[3].push(4); console.log(inventory1); // ['a', 'b', 'c', [1, 2, 3]]; console.log(inventory2); // ['a', 'b', 'c', [1, 2, 3, 4]];

Attempting to deleting an array for which the pointer has been duplicated will not free up memory. The original pointer will be deleted, but the object will be preserved because the second pointer requires it. This is a form of closure.

Related posts:

Helpful references:

Have feedback on this topic?