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 -
- using spead operator {...}
- 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 -
- using JSON.parse(JSON.stringify(---object---))
- 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 -
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
Loading comments...