Profile Picture

Lazy Panda

Developer

Posts
56
Comments
48
Likes
75
Posts
56
Comments
48
Likes
75
sidebar

Explanation on Shallow copy, Deep copy in JavaScript or TypeScript using structuredClone

In day to days dev work, we always wanted to copy some values to other variables and run different kinds of logic to manipulate the Object properties value. Sometimes we lost the original Object by doing calculations and updating values on parent object properties. For that, we need different types of Object copies. 

Shallow Copy

In javascript, most of the copy is a Shallow Copy, which means changes in the object are deeply nested and that change will be visible to copied object as well as the original object. 

There are two way you can do a Shallow copy - 

  1. using spead operator {...}
  2. using Object.assign() method

 

const parentObject = {

name: 'Lazy Panda',

profile: 'Developer',

address: {

country: 'IN',

state: 'WB'

}​​​​​​

}

 

// copying original object to another variable

const childObject = {...parentObject}

 

const anohterChildObject = Object.assign({}, parentObject);

 

// Adding or changing a property directly on the shallow copy will only affect the copy variable, not the original​​​​

childObject.name = 'Lazy Panda Tech'; 

 

// Where as, changing the value in nested property 'address.country' will affect both the parent & child object 

childObject.address.country = 'India'; 

 

 

 

 

Have look with console log values as well. 

// based on above example, if change the name only 

childObject.name = 'Lazy Panda Tech'; 

 

then console log will be like - 

Original Object

{

name: 'Lazy Panda',

profile: 'Developer',

address: {

country: 'IN',

state: 'WB'

}​​​​​​

}

Child Object

{

name: 'Lazy Panda Tech',

profile: 'Developer',

address: {

country: 'IN',

state: 'WB'

}​​​​​​

}


const childObject = {...parentObject} 

OR 

const anohterChildObject = Object.assign({}, parentObject);

 

// Now if we change the nested property value like 'address' along with above changes

childObject.name = 'Lazy Panda Tech'; 

childObject.address.country = 'India'; 

 

// Now both the object will have following impact

Original Object

{

name: 'Lazy Panda', --> No impact

profile: 'Developer',

address: {

country: 'India', --> impacted

state: 'WB'

}​​​​​​

}

Child Object

{

name: 'Lazy Panda Tech', --> impacted

profile: 'Developer',

address: {

country: 'India', --> impacted

state: 'WB'

}​​​​​​

}

 

 

 

The expression {...childObject} iterates over the (enumerable) properties of parentObject using the Spread Operator. It uses the property name and value, and assigns them one by one to a freshly created, empty object. As such, the resulting object is identical in shape, but with its own copy of the list of properties and values. The values are copied, too, but so-called primitive values are handled differently by the JavaScript value than non-primitive values. 


Deep Copy

The opposit of shallow copy is a deep copy. A deep copy algorithm also copies an object’s properties one by one, but invokes itself recursively when it finds a reference to another object, creating a copy of that object as well.

There are two way we can use deep copy - 

  1. using JSON.parse(JSON.stringify(---object---)) 
  2. using structuredClone() API call. 

Let's see how it works with example - 

const parentObject = {

name: 'Lazy Panda',

profile: 'Developer',

address: {

country: 'IN',

state: 'WB'

}​​​​​​

}

 

// copying original object to another variable

const childObject = JSON.parse(JSON.stringify(parentObject)) 

 

const anohterChildObject = structuredClone(parentObject);

 

// Adding or changing a property directly on the deep copy will affect the copy variable, not the original

childObject.name = 'Lazy Panda Tech'; 

 

// Changing the value in nested property 'address.country' will affect both the parent & child object 

childObject.address.country = 'India'; 

 

 

 

 

// based on above example, if change the name only

childObject.name = 'Lazy Panda Tech'; ​​​​​​​

 

then console log will be like - 

Original Object

{

name: 'Lazy Panda', --> No Impact

profile: 'Developer',

address: {

country: 'IN',

state: 'WB'

}​​​​​​

}

Child Object

{

name: 'Lazy Panda Tech', --> Impacted

profile: 'Developer',

address: {

country: 'IN',

state: 'WB'

}​​​​​​

}


const childObject = JSON.parse(JSON.stringify(parentObject));​​​​​​​

​​​​​​​OR 

const anohterChildObject = structuredClone​​​​​​​(parentObject); // currently it only support on firefox, nodejs and deno

 

// Now if we change the nested property value like 'address' along with above changes

childObject.name = 'Lazy Panda Tech'; 

childObject.address.country = 'India'; ​​​​​​​​​​​​​​

 

// Now both the object will have following impact

Original Object

{

name: 'Lazy Panda', --> No impact

profile: 'Developer',

address: {

country: 'IN', --> No impact

state: 'WB'

}​​​​​​

}

Child Object

{

name: 'Lazy Panda Tech', --> impacted

profile: 'Developer',

address: {

country: 'India', --> impacted

state: 'WB'

}​​​​​​

}

 

 

Structured cloning can only work in following web browsers and platforms -

chrome-firefox

 

Performance 

JSON.parse() was the fastest option for very small objects. Techniques that relied on structured cloning were (significantly) faster for bigger objects. Considering that the new structuredClone() comes without the overhead of abusing other APIs and is more robust than JSON.parse().

Thanks & Happy Coding!

- LP