Clone an Object in JavaScript: 4 Best Ways [Updated 2022]

In JavaScript, objects are reference values.

This means you cannot use the assignment operator (=) to clone objects. If you do, you are just creating an alias for the existing object.

To clone a JavaScript object correctly, you have 4 different options:

  1. Use the spread operator.
  2. Call the Object.assign() function.
  3. Use JSON parsing.
  4. Use the structuredClone() function.

Here is a quick example of each approach:

const data = { name: "Alice", age: 26 }

// 1
const copy1 = { ...data }

// 2
const copy2 = Object.assign({}, data)

// 3
const copy3 = JSON.parse(JSON.stringify(data))

// 4
const copy4 = structuredClone(data)

Important:

  • The 1st and the 2nd approach create a shallow copy.
  • The 3rd and the 4th approach create a truly independent deep copy.

But how do these approaches work?

Why all the hassle for such a simple operation?

In this guide, you learn why cloning an object is a bit of a mess in JavaScript. You also learn what a shallow copy is and what is a deep copy. Furthermore, you learn in more detail how the approaches seen above work.

Why Cloning with (=) Operator Fails in JavaScript?

In JavaScript, objects are reference values by nature.

This means a variable that represents a JavaScript object is a reference to the object in memory.

When you use the assignment operator to assign an object to a variable, you are essentially creating a new reference to the object.

Here is an illustration of what I mean:

Trying to copy with assignment operator does not create a copy!
“Cloning” with assignment creates a reference to the same object. Thus it does not copy anything.

In code, it looks as if you create a copy of the original data object.

But you are actually creating a new alias to the data object.

In other words, the {name: “Alice”, age: 23} object is now known as data and dataCopy.

Because the two variables both reference the same object in memory, making changes to the object is seen in both variables.

All in all, the assignment operator does not create a copy of an object. It just creates an additional name to the original object.

This is why it is a bit of a hassle when it comes to copying objects in JavaScript.

Next, we are going to take a look at how to actually copy an object in JavaScript. You will learn two important concepts related to copying:

  • Shallow copy
  • Deep copy

Shallow Copy in JavaScript

A shallow copy is a “one-level-deep” copy.

The shallow-copied object has references to the properties of the original object.

In other words, nested objects are not recursively copied.

This is important to understand. It is confusing if you have not heard about it before.

For instance, this really popular article got it all wrong. Apparently, GeeksForGeeks also got it wrong. Both these articles are found in the top results of Google, so be careful!

Anyway, to make any sense of what this means, you need to see some examples.

One way to create a shallow copy in JavaScript is by using the spread operator ().

Let’s create a data object and a shallow copy of it. Then let’s change the value of a property of the original object to see what happens:

const data = { name: "Alice", age: 26 }
const dataCopy = { ...data }

data.age = 1000

console.log(data.age)
console.log(dataCopy.age)

Output:

1000
26

As you can see, changing the data.age only changed the age property of the data object.

It did not affect the dataCopy object.

Makes sense.

However, dataCopy is a shallow clone of the original data object.

In other words, if the object consists of nested child objects, changing the child objects’ properties is also going to be visible in the copied object!

Let me show you what I mean.

Let’s add an array of hobbies to the data object from the previous example. Then let’s create a shallow copy of data and change one of the hobbies to see what happens:

const data = { name: "Alice", age: 26, hobbies: ["Jogging", "Tennis", "Gym"] }

const dataCopy = { ...data }

data.hobbies[0] = "Golf"

console.log(data.hobbies)
console.log(dataCopy.hobbies)

Output:

["Golf", "Tennis", "Gym"]
["Golf", "Tennis", "Gym"]

As you can see, changing the first hobby from “Jogging” to “Golf” affects both data and dataCopy.

This is why the copy in question is called shallow or “one level deep”.

Changing the properties of the original object does not affect the cloned object. But changing the properties of the child objects of the copied object does.

But why does this happen?

As mentioned earlier, a shallow-copied object’s properties reference the original object’s properties.

This means a shallow copy shares the same underlying values as the original object.

Shallow cloning an object in JavaScript

If you now change a property of the original object, such as the age, you actually create a completely new value for the age.

Because you are dealing with two independent objects, this change is not reflected in the copied object.

The copied object has no idea about the new age value.

But if the original object has a mutable child object, such as the hobbies array, changes made to the array are seen in both the original object as well as the copied object.

This is because the copied object’s hobbies array points to the original hobbies array.

When you change a value in the original hobbies array, you are directly modifying the array instead of creating a new one.

Because the copied object references that same array, the changes are also visible there.

But if you replaced the whole hobbies array with a new one, the changes would not be visible in the cloned object.

Feel free to play with the examples to get a better grasp of how shallow copying works.

At this point, you may wonder how to create truly independent copies of objects in JavaScript.

The shallow copy only creates a “one-level-deep” cloned object.

This is not always what you want.

This is where the concept of deep cloning comes in handy.

Deep Copy in JavaScript

In JavaScript, the deep copy means a completely independent copy of the original object.

One way to create a deep copy is by using the built-in JSON module.

For instance:

const data = { name: "Alice", age: 26, hobbies: ["Jogging", "Tennis", "Gym"] }

const dataCopy = JSON.parse(JSON.stringify(data))

data.hobbies[0] = "Golf"

console.log(data.hobbies)
console.log(dataCopy.hobbies)

Output:

["Golf", "Tennis", "Gym"]
["Jogging", "Tennis", "Gym"]

As you can see, now the changes in the original object’s hobbies array were not reflected in the copied object’s one.

A deep copy allows you to create a completely independent copy of the original object.

Now you understand how copying works in JavaScript.

More importantly, you understand that the assignment operator does not copy objects.

You also learned that there are two types of copies in JavaScript: shallow copy and deep copy.

Make sure to check my complete guide to JSON.

Finally, let’s move on to the 4 different ways to clone objects in JavaScript.

4 Ways to Clone Objects in JavaScript

In JavaScript, there are 4 popular ways to create copies of objects.

To create a shallow copy, you can:

  1. Use the spread syntax ().
  2. Call Object.assign() function.

To create a deep copy (a completely independent copy), you have two options:

  1. Use JSON parsing
  2. Use the structuredClone() function.

Let’s go through each of these approaches.

1. Use the spread operator (Shallow Copy)

In JavaScript, you can use the three dots (…) operator to spread the properties of an object to where one or more key-value pair is expected.

Learn more about the spread operator here.

One way you can utilize this operator is to create a copy of an object.

For example, let’s create a shallow copy and modify the original object’s property:

const data = { name: "Alice", age: 26 }
const dataCopy = { ...data }

data.age = 1000

console.log(data)
console.log(dataCopy)

Output:

{
  age: 1000,
  name: "Alice"
}

{
  age: 26,
  name: "Alice"
}

As you can see, the changes made to the original object are not visible in the copy.

This is the shortest and the most concise way to clone an object.

However, this is a shallow copy (not a fully independent copy).

If you did not read the shallow copy chapter in this guide, go ahead and do so. It is important to understand what it means and why it can cause issues.

Let’s see one more way to create a shallow copy.

2. Call the Object.assign() function (Shallow Copy)

Another way to create a shallow copy of a JavaScript object is by calling the Object.assign() function.

For example:

const data = { name: "Alice", age: 26 }
const dataCopy = Object.assign({}, data)

data.age = 1000

console.log(data)
console.log(dataCopy)

Output:

{
  age: 1000,
  name: "Alice"
}

{
  age: 26,
  name: "Alice"
}

Now you have seen two ways to create shallow copies in JavaScript.

Next, let’s create some truly independent deep copies.

3. Use JSON parsing (Deep Copy)

As discussed earlier, the problem with a shallow copy is that it does not recursively copy nested objects.

To create a truly independent copy of an object in JavaScript, you need to know how to create a deep copy.

One way to create a deep copy is by using the JSON.parse() and JSON.stringify() functions.

For example:

const data = { name: "Alice", age: 26 }
const dataCopy = JSON.parse(JSON.stringify(data))

data.age = 1000

console.log(data)
console.log(dataCopy)

Output:

{
  age: 1000,
  name: "Alice"
}

{
  age: 26,
  name: "Alice"
}

This approach converts a JavaScript object to JSON and then back to a JavaScript object.

This is what creates the independent copy.

However, this method has its own caveats too.

For instance, if your object has a Date value, the JSON.stringify() function converts it to a string.

In other words, the copied object is independent but it could consist of values of the incorrect type in some cases.

To overcome this, there is one more deep copy approach you need to see.

It is called the structuredClone().

4. The structuredClone() Function (Deep Copy)

The structuredClone() method creates a deep clone of an object.

The structuredClone() is a brand new addition to JavaScript. Please see the Browser Compatibility chart of the method.

structuredClone() browser compatibility for cloning objects
Source: developer.mozilla.org

Anyway, let’s see an example of creating a deep copy with the structuredClone() method:

const data = { name: "Alice", age: 26 }
const dataCopy = structuredClone(data)

data.age = 1000

console.log(data)
console.log(dataCopy)

Output:

{
  age: 26,
  name: "Alice"
}

As you can see, the changes made to the original object are not visible in the copied object.

Feel free to try these examples out to get a better feeling on how they work.

Also, feel free to mix in some nested child objects and see how changing them behaves with shallow copies and deep copies.

Conclusion

Today you learned a bunch of different ways to copy an object in JavaScript.

As you learned, some of these methods create a shallow copy and others create a deep copy.

A shallow copy is a “one-level-deep” copy. In a shallow copy, any nested properties are not copied. Instead, they refer back to the properties of the original object.

To create an independent copy, you want to create what is called a deep copy.

To create a shallow copy, you have two common options:

  • The spread operator
  • The Object.assign() method.

To create an independent deep copy, you also have two options:

  • The JSON parsing approach
  • The structuredClone() method.

Thanks for reading.

Happy coding!

Further Reading

JavaScript Interview Questions