HOLIDAY SALE! Save 50% on Membership with code HOLIDAY50. Save 15% on Mentorship with code HOLIDAY15.

3) Connect Four Lesson

How to Deep Copy an Array in JavaScript

9 min to complete · By Ian Currie

In this lesson, you'll learn about methods of deep copying arrays and why it's important.

Pass Arrays By Reference

If you remember back to the lesson on passing arrays by reference, you'll recall this example:

const a = [];
const b = a;
b[0] = 1;
console.log(a); // [1] !

This is because when you assign an array or object to a variable, you are actually assigning a reference to the array or object:

Diagram showing variables assigned to reference to array

How to Create a Copy Of an Array

If you want to copy an array, you have to do so explicitly.

The simplest way would be to create a new array and push all the elements of the other array one by one:

const original = [1, 2, 3, 4, 5];
const copy = []; // new array

original.forEach((n) => copy.push(n));
console.log(copy); // [1,2,3,4,5]

A shortcut is to just use the spread syntax:

const original = [1, 2, 3, 4, 5];
const copy = [...original];

If your arrays are only going to be one-dimensional this method will work, however, if you have multi-dimensional arrays, this you'll get a shallow copy:

const original = [
	[1, 2, 3],
	['a', 'b', 'c']
];
const copy = [...original];
original[0][0] = 4;
console.log(copy); // [[4,2,3], ["a","b","c"]]

In this example, the enclosing arrays, the outer arrays of both original and copy are unique, but they store references to other arrays, and while they are different arrays, they have exactly the same contents, two references to the same two arrays.

If you roughly know the shape of the array, you can do a combination of looping and spreading:

const original = [
	[1, 2, 3],
	['a', 'b', 'c']
];
const copy = []; // new array

original.forEach((subArray) => copy.push([...subArray]));
console.log(copy); // [[1,2,3], ["a","b","c"]]

Now copy is a true copy with its own sub-arrays.

Three Ways to Create a Deep Copy of an Array

There are three ways you can go about creating a deep copy of an array or object with arbitrary depth:

  • Write a recursive function to do so (recursion covered later in the course)
  • Use the JSON hack
  • Use the Lodash library function cloneDeep()

Write a Recursive Function

This is the most difficult method, but it's also the most instructive. You'll learn about recursion later in the course, but the basic idea is that you write a function that calls itself:

function deepCopy(inputArray) {
	const copy = [];
	inputArray.forEach((item) => {
		if (Array.isArray(item)) {
			copy.push(deepCopy(item));
		} else {
			copy.push(item);
		}
	});
	return copy;
}

This function will work for an array of any depth, but it will not work for an object. You'll have to write a separate function for that.

Use the JSON Hack

The JSON hack involves using the JSON object to .stringify() the array or object, and then call .parse() on the resultant string:

const original = [
	[1, 2, 3],
	['a', 'b', 'c']
];
const originalString = JSON.stringify(original);
const copy = JSON.parse(originalString);
console.log(copy); // [[1,2,3], ["a","b","c"]]

This works for an array or object of any depth provided they don't have special values like functions. If your array or object has a function, this method will not work.

Likewise with other special non-JSON values like undefined, NaN, Infinity, -Infinity, Date objects and other kinds of special objects, these won't work with the JSON hack.

Just Use a Library

The Lodash library is a utility library that has lots of useful functions, cloneDeep() being one of them. If you want to use it that way, you'll have to link the Lodash script from a CDN or download it into your project.

Sometimes, well defined problems have well defined solutions, and when working on professional projects, it can be best to use a library that has been tested and used by thousands of developers.

While learning, though, it's fun and instructive to build your own solutions.

Colorful illustration of a light bulb

It can be a shame to import a library just for one function. If that's the case, you can manually copy the function from the source code. Just be sure to attribute it correctly.

If you know how to set up a Node.js with a bundler like Rollup, you can import just the function you need from the Lodash source code, and Rollup will take care of only including the code you need in your final bundle.

Working with Node.js and bundlers is beyond the scope of this course, but it will be covered in future courses.

Summary: How to Create a JavaScript Deep Copy Array

You've navigated through the complexities of deep copying arrays in JavaScript, grasping the nuances of value versus reference. You've:

  • Understood the concept of passing by reference, which means any changes made to a new variable will affect the original array if it was assigned by reference.
  • Learned how to create a shallow copy using methods like spreading elements with [...original], which suffices for one-dimensional arrays but not for nested arrays.
  • Explored the limitations of shallow copies, where nested arrays are still referenced rather than copied, leading to potential side effects.
  • Discovered methods to create deep copies of arrays, including a recursive function that copies each level of the array, suitable for arrays of any depth.
  • Examined the JSON hack as a convenient workaround that involves stringifying and parsing an array, which works unless the array includes non-JSON-compatible values like functions.
  • Considered the use of utility libraries like Lodash, which provides a cloneDeep function for an efficient and reliable deep copy.