In this post, you'll find 3 easy ways to perform shallow clone (aka copy) of objects in JavaScript.
As a bonus, I'm going to show how you can also update, add, or remove properties in place on the clone. That's useful when you want to perform an update on the object in an immutable manner.
Note
The 3 ways to clone objects described in this post perform shallow copy.
A shallow copy means that only the actual object gets copied. If the copied object contains nested objects — these nested objects aren't get cloned.
Table of Contents
1. Cloning using object spread
The simplest way to clone a plain JavaScript object is to invoke the object spread operator:
const clone = { ...object};
Where object
is the object you'd like to copy, and clone
is the shallow copy of object
.
For example, let's create a shallow copy of hero
object:
const hero = { name: 'Batman', city: 'Gotham'};const heroClone = { ...hero};heroClone; // { name: 'Batman', city: 'Gotham' }hero === heroClone; // => false
heroClone
is a clone object of hero
, meaning that it contains all the properties of hero
.
hero === heroClone
evalutes to false
— hero
and heroClone
are, nevertheless, difference object instances.
1.1 Object spread bonus: add or update cloned props
An immediate benefit of using object spread is that you can update or add new properties to the cloned object in place if you need it.
Let's clone the hero
object, but update name
property to a different value and add a new property realName
:
const hero = { name: 'Batman', city: 'Gotham'};const heroEnhancedClone = { ...hero, name: 'Batman Clone', realName: 'Bruce Wayne'};heroEnhancedClone; // { name: 'Batman Clone', city: 'Gotham', realName: 'Bruce Wayne' }
2. Cloning using object rest
Another good way to shallow clone objects is by using the object rest operator:
const { ...clone } = object;
Again, let's use the rest operator to make a copy of hero
object:
const hero = { name: 'Batman', city: 'Gotham'};const { ...heroClone } = hero;heroClone; // { name: 'Batman', city: 'Gotham' }hero === heroClone; // => false
After applying the rest operator const { ...heroClone } = hero
, the heroClone
variable contains a copy of hero
object.
2.1 Object rest bonus: skip cloned props
A nice bonus when using object rest is the ability to skip certain properties when cloning.
For example, let's create a clone of hero
object, but skip city
property in the clone:
const hero = { name: 'Batman', city: 'Gotham'};const { city, ...heroClone } = hero;heroClone; // { name: 'Batman' }
2.2 Super bonus: combining object spread and rest
Object spread brings the bonus of updating or adding new properties, while object rest has the benefit of skipping properties in the resulting clone.
Can you combine object spread and rest into one statement to inherit all these benefits? Yes, you can!
Let's clone the hero
object, also adding a new property realName
and skipping the property city
:
const hero = { name: 'Batman', city: 'Gotham'};const { city, ...heroClone } = { ...hero, realName: 'Bruce Wayne'};heroClone; // { name: 'Batman', realName: 'Bruce Wayne' }
Combining the object spread and rest to clone objects and perform properties manipulation in a single statement is great!
3. Cloning using Object.assign()
Finally, Object.assign(target, ...sources)
let's you peform the same object clone:
const clone = Object.assign({}, object);
Let's use Object.assign()
in practice and create a clone object of hero
object:
const hero = { name: 'Batman', city: 'Gotham'};const heroClone = Object.assign({}, hero);heroClone; // { name: 'Batman', city: 'Gotham' }hero === heroClone; // => false
Object.assign({}, hero)
creates a clone of hero
object by merging the second argument hero
into the first argument {}
.
3.1 Object.assign() bonus: add or update cloned props
Object.assign()
enables also to update or add new properties to the clone.
Let's copy the hero
object, but at the same time update name
property:
const hero = { name: 'Batman', city: 'Gotham'};const heroClone = Object.assign({}, hero, { name: 'Batman Clone' });heroClone; // { name: 'Batman Clone', city: 'Gotham' }
Object.assign({}, hero, { name: 'Batman Clone' })
creates the object in 2 steps.
First, the second argument hero
is merged into the first argument {}
. This equals to { name: 'Batman', city: 'Gotham' }
.
Second, the third argument { name: 'Batman Clone' }
is merged into the result from the previous step, overwriting the property name
. Finally, you get the object { name: 'Batman Clone', city: 'Gotham' }
.
4. Summary
JavaScript provides 3 good ways to clone objects: using spread operator, rest operator and Object.assign()
function.
Aside from just cloning objects, using object spread and Object.assign()
lets you add or updated properties when creating the clone.
Rest operator also gives the benefit of skipping certain properties when cloning.
And what's great, you can combine the object spread and rest in a single statement, so you can clone the object, and at the same time add, update or skip properties from being cloned.
That's useful if you'd like to embrace the immutability and be able to manipulate the cloned object's properties in place.
What other good ways to clone objects in JavaScript do you know?