A shallow copy or clone means that only the actual object gets copied. Shallow cloning does not copy nested objects.
Just remember that JavaScript objects are mutable by nature and stored as a reference. So, when you assign the object to another variable, then you’re just assigning the memory address of the object to that variable. When we change anything in either of the object, it will reflect in the other.
JavaScript provides 3 best ways to clone or copy objects,
- Using object spread
- Using object rest
- Using Object.assign() method
Cloning using object spread
This one is the simplest way to clone a plain JavaScipt object,
- const clone = {
- ...sampleObject
- };
Where sampleObject is the object which we want to copy, and clone is the shallow copy of object.
Let’s take an example of creating a shallow copy of the “person” object,
- const person = {
- name: 'John',
- city: 'Gotham'
- };
- const personClone = {
- ...person
- };
- console.log(personClone);
Here, personClone is a cloned object of person, which means that it contains all the properties of the person that we declared.
Object spread: add or update clone props
One of the benefit of using object spread is that you can update or add new properties to the cloned object.
Let’s clone the “person” object, but in this case we also want to update the name property with a different value and we also want to add a new property age in the object.
- const person = {
- name: 'John',
- city: 'Gotham'
- };
- const personClone = {
- ...person,
- name: 'John Wayne',
- age: 23
- };
- console.log(personClone);
-
As you can see, in the console the value of the name property changed with a property named age added to the object.
Cloning using object rest
Another way to shallow clone an object is by using the object rest operator,
- const {...clone } = object
Let’s see an example for copying person object using rest operator,
- const person = {
- name: 'John',
- city: 'Gotham'
- };
- const { ...personClone } = person;
- console.log(personClone);
As shown in the above example, after applying the rest operator const { …personClone } = person, the personClone variable contains a copy of person object.
Object rest: skip cloned props
Object rest has an ability to skip certain properties when cloning.
For example, let’s create a clone of person object, but skip city property of the object while cloning,
- const person = {
- name: 'John',
- city: 'Gotham'
- };
-
- const { city, ...personClone } = person;
- console.log(personClone);
Object rest: combining object spread and rest
Object spread has an ability to allow updating or adding new properties to the object, while object rest has an ability of skipping properties in the resulting clone object.
Now let’s try to combine both into one statement to inherit all the benefits.
Let’s clone the person object, where would add a new property age and skip the property city,
- const person = {
- name: 'John',
- city: 'Gotham'
- };
- const { city, ...personClone } = {
- ...person,
- age: 23
- };
- console.log(personClone);
Cloning using object.assign()
Object.assign function lets you clone the same object,
- const clone = Object.assign({}, object);
Let’s create a clone object of person object using Object.assign(),
- const person = {
- name: 'John',
- city: 'Gotham'
- };
-
- const personClone = Object.assign({}, person);
- console.log(personClone);
Object.assign({ }, person) creates a copy of the person object by merging the second argument person into the first argument { } of the assign method.
Object.assign( ): add or update cloned props
Object.assign( ) also has an ability to add and update properties to the clone.
Let’s create copy of person object, but at the same time update name property’s value,
- const person = {
- name: 'John',
- city: 'Gotham'
- };
-
- const personClone = Object.assign({}, person, { name: 'John Wayse' });
- console.log(personClone);
Object.assign({ }, person, { name: 'John Wayse' }) creates the object in 2 parts,
Step 1
The second argument is merged into the first argument { } of the assign method. This results in { name: 'John', city: 'Gotham' }.
Step 2
The third argument { name: 'John Wayse' } is merged into the result from the previous step that is the result of our second step, overwriting the property name which we already have in our third argument. So our final resulting object will be { name: 'John Wayse', city: 'Gotham' }.
Summary
In this article, I discussed about common characteristics of objects. After that we saw how we can clone objects using spread operator, rest operator and Object.assign() function. And we also discussed about update, add or remove properties in place on the clone with examples.