How to clone Object in JavaScript
Cloning objects in JavaScript is a common task encountered in interviews and practical coding scenarios. There are various methods to achieve this, each with its own advantages and limitations. In this guide, we'll explore shallow cloning versus deep cloning and discuss different techniques along with their pros and cons.
Shallow cloning VS Deep cloning
Before delving into the disparity among these methods, grasping the concepts of shallow and deep copying is imperative.
Shallow Cloning or shallow copy
Shallow copy duplicates the original object's properties but maintains references to nested objects. Consequently, modifications to nested objects in the copied instance affect the original.
In short, Shallow cloning creates a new object with copies of the original object's properties, but it does not deeply clone nested objects.
Deep Cloning or deep copy
On the other hand deep copy replicates the original object and all its properties and nested objects. Both objects become entirely independent, ensuring changes to one don't impact the other.
Method 1 : Object.assign()
To shallow copy an object in JavaScript, utilize the Object.assign()
method, which accepts two objects as arguments (the target and the source) and returns an exact replica of the source object..
const targetObj = { userName: "rubi", email: "rubi@gmail.com" };
const sourceObj = { userName: "vaibhav", email: "vaibhav@gmail.com" };
const returnedTarget = Object.assign(targetObj, sourceObj);
console.log(targetObj);
// Expected output: Object { userName: "vaibhav", email: "vaibhav@gmail.com" }
console.log(returnedTarget === targetObj);
// Expected output: true
const user = {
userName: "vaibhav",
email: "vaibhav@gmail.com",
address : {
city : "Ambala",
country : "India"
}
}
const newUser = Object.assign({}, user)
console.log(newUser);
// Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Ambala', country: 'India' } }
In the given example, we initialize an object named user
containing user information, including a nested address
object. Subsequently, we shallow copy the user
object using Object.assign()
into a new object named newUser
.
It's important to note that although newUser
is a shallow copy of user
, any modifications made to nested properties within newUser
will also affect the corresponding properties in the original user
object.
This phenomenon is illustrated in the explanation provided: if we alter the address
property within newUser
, it will concurrently modify the address
property within the user
object as well.
Method 2 : Spread operator
Another approach for shallow copying is using the spread operator (...
). The spread operator facilitates the expansion of an object's properties into a new object. Here's an example:
const user = {
userName: "vaibhav",
email: "vaibhav@gmail.com",
address : {
city : "Ambala",
country : "India"
}
}
const newUser = { ... user }
console.log(newUser);
// Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Ambala', country: 'India' } }
Method 3 : JSON.parse() and JSON.stringify()
A common approach for deep copying an object in JavaScript involves using the JSON.parse()
and JSON.stringify()
methods. JSON.stringify()
converts a JavaScript object into a JSON string, while JSON.parse()
converts a JSON string back into a JavaScript object.
Here's an example showcasing these methods:
const user = {
userName: "vaibhav",
email: "vaibhav@gmail.com",
address : {
city : "Ambala",
country : "India"
}
};
const newUser = JSON.parse(JSON.stringify(user));
newUser.address.city = "Los Angeles";
newUser.address.country = "US"
console.log(newUser);
// Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Los Angeles', country: 'US' } }
console.log(user);
// Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Ambala', country: 'India' } }Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Ambala', country: 'India' } }
In this example, the original object is first converted into a JSON string using JSON.stringify()
. Subsequently, a new object is created by parsing the JSON string with JSON.parse()
. This method ensures a deep copy of the original object, including all nested objects.
However, it's essential to note some limitations:
Performance may suffer for large objects due to string conversion and parsing.
Works only with objects that can be serialized to JSON. Objects with circular references, functions, or non-serializable properties (such as
Date
,RegExp
, orMap
andSet
) cannot be cloned using this method.
Method 4 : structuredClone()
Another approach for deep copying involves using the structured cloning algorithm. structuredClone()
is not a built-in JavaScript function; it's part of the structured cloning algorithm provided by the HTML Living Standard. It's typically available in environments such as web workers and service workers.
const user = {
userName: "vaibhav",
email: "vaibhav@gmail.com",
address : {
city : "Ambala",
country : "India"
}
};
const newUser = structuredClone(user);
newUser.address.city = "Gurugram";
console.log(newUser);
// Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Gurugram', country: 'India' } }
console.log(user);
// Expected output: Object { userName: 'vaibhav', email: 'vaibhav@gmail.com', address: { city: 'Ambala', country: 'India' } }
Considerations:
Performance: JSON methods might be slower for large objects due to string conversion.
Compatibility: JSON methods only work with serializable objects, excluding functions and non-serializable properties.
Availability: structuredClone() is available in environments like web and service workers.
Libraries: Libraries like Lodash and Ramda offer robust solutions for deep cloning, accommodating complex data structures and edge cases.
Object cloning in JavaScript is a nuanced process with various approaches catering to different scenarios. Understanding these techniques equips developers to efficiently manage object data in their projects.
Subscribe to my newsletter
Read articles from Rubi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Rubi
Rubi
Backend developer with a passion for crafting efficient and inventive solutions. I prioritize continuous learning to expand my expertise and skill set.