How to Copy Objects in JavaScript: What Are Shallow and Deep Copies and How Can You Achieve Them?
Copying Objects in JavaScript: Shallow and Deep Copy Explained
In JavaScript, when dealing with objects, it is often necessary to create copies of an object. However, copying objects isn’t as simple as copying primitive data types like numbers or strings. This is because objects in JavaScript are reference types. When an object is assigned to a variable, that variable holds a reference (or pointer)
to the object, not the object itself.
There are two main types of copying in JavaScript:
Shallow Copy
Deep Copy
1. Shallow Copy in JavaScript
A shallow copy
creates a new object, but it only copies the top-level
properties of the original object. If there are nested objects, only references to those objects are copied, meaning both the original and copied objects share the same nested objects. Therefore, changes made to nested objects
in either the original or the copied object will reflect
in both the object.
Methods to Achieve a Shallow Copy:
Using
Object.assign()
Using the spread operator
...
Using Lodash’s Library
_.clone()
Method
Example 1: Shallow Copy Using Object.assign()
let dog = {
name: 'Tommy',
breed: 'Labrador',
details: {
age: 3,
address: 'Delhi'
}
};
// Creating a shallow copy of 'dog' using Object.assign()
let dogCopy = Object.assign({}, dog);
// Modifying properties in the original object
dog.name = 'Charlie'; // Changes the original object
dog.details.age = 4; // Modifies the nested object
console.log(dog); // { name: 'Charlie', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
console.log(dogCopy); // { name: 'Tommy', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
Explanation:
- The shallow copy only copies the top-level properties of the object
dog
.
- The
details
object is still shared betweendog
anddogCopy
, so changing the nested objectdetails.age
indog
also reflects indogCopy
also.
Example 2: Shallow Copy Example Using Spread Operator (...
)
let dog = {
name: 'Tommy',
breed: 'Labrador',
details: {
age: 3,
address: 'Delhi'
}
};
// Creating a shallow copy of 'dog' using the spread operator
let dogCopy = { ...dog };
// Modifying properties in the copied object
dog.name = 'Charlie'; // Original object modified
dog.details.age = 4; // Nested object modified
console.log(dog); // { name: 'Charlie', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
console.log(dogCopy); // { name: 'Tommy', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
Explanation:
Like
Object.assign()
, the spread operator creates a shallow copy of the top-level properties.The
details
object is still shared betweendog
anddogCopy
, so changing the nested objectdetails.age
indog
also reflects indogCopy
also.
Example 3: Shallow Copy Example Using Lodash’s Library _.clone()
Method
To use Lodash in your JavaScript project, you first need to install it. If you’re working in a Node.js environment or using package managers like npm or yarn, you can install Lodash with the following commands:
- Using npm:
npm install lodash
- Using yarn:
yarn install lodash
After installing Lodash, you can require it in your JavaScript file and start using its various utility functions, including _.clone()
for shallow copying.
// Require the lodash library
const _ = require('lodash');
// Original object - 'dog'
let dog = {
name: 'Tommy',
breed: 'Labrador',
details: {
age: 3,
address: 'Delhi'
}
};
// Creating a shallow copy of 'dog' using _.clone()
let dogCopy = _.clone(dog);
// Modifying properties in the copied object
dog.name = 'Charlie'; // Original object modified
dog.details.age = 4; // Nested object modified
console.log(dog); // { name: 'Charlie', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
console.log(dogCopy); // { name: 'Tommy', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
Explanation:
Lodash’s
_.clone()
creates a shallow copy of the object, meaning only the top-level properties are copied. In this case, properties likename
andbreed
are copied directly.The
details
object is still shared betweendog
anddogCopy
, so changing the nested objectdetails.age
indog
also reflects indogCopy
also.Lodash’s
_.clone()
is similar to theObject.assign()
and the spread operator (...
) when it comes to shallow copying, as it doesn't handle nested objects deeply.
2. Deep Copy in JavaScript
A deep copy creates a complete, independent copy of the original object, including all nested objects. Modifying the deep copy does not affect the original object, and vice versa. In other words, the deep copy replicates the entire structure of the object.
Methods to Achieve a Deep Copy:
Using
JSON.parse(JSON.stringify(object))
Manually using recursive functions
Using Lodash’s Library
_.cloneDeep()
Method
Example 1: Deep Copy Using JSON.parse(JSON.stringify(object))
How it works?
Convert to JSON String:
JSON.stringify(object)
takes the original object and converts it into a JSON string, copying all its properties, including nested objects.Parse Back to Object:
JSON.parse(jsonString)
takes the JSON string and converts it back into a new JavaScript object. This new object is independent of the original, meaning changes to one do not affect the other.
let dog = {
name: 'Tommy',
breed: 'Labrador',
details: {
age: 3,
address: 'Delhi'
}
};
// Creating a deep copy using JSON.parse(JSON.stringify())
let dogCopy = JSON.parse(JSON.stringify(dog));
// Modifying properties in the original object
dog.name = 'Charlie'; // Original object modified
dog.details.age = 4; // Nested object modified
console.log(dog); // { name: 'Charlie', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
console.log(dogCopy); // { name: 'Tommy', breed: 'Labrador', details: { age: 3, address: 'Delhi' } }
Explanation:
JSON.parse(JSON.stringify(dog))
creates a deep copy of thedog
object.Changes to the original
dog
object do not affectdogCopy
.
Example 2: Deep Copy Using a Recursive Function
let dog = {
name: 'Tommy',
breed: 'Labrador',
details: {
age: 3,
address: 'Delhi'
}
};
// Recursive function to create a deep copy of an object
function deepCopy(obj) {
// Initialize an empty object to hold the copy
let copy = {};
// Iterate over each key in the original object
for (let key in obj) {
// Check if the property is an object and not null (to avoid copying null values)
if (typeof obj[key] === 'object' && obj[key] !== null) {
// Recursively call deepCopy for nested objects and assign the result to the corresponding key in the copy
copy[key] = deepCopy(obj[key]);
} else {
// Copy primitive values directly to the new object
copy[key] = obj[key];
}
}
// Return the deep copy of the object
return copy;
}
// Create a deep copy of the original dog object
let dogCopy = deepCopy(dog);
// Modifying properties in the original object
dog.name = 'Charlie'; // Original object modified
dog.details.age = 4; // Nested object modified
console.log(dog); // { name: 'Charlie', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
console.log(dogCopy); // { name: 'Tommy', breed: 'Labrador', details: { age: 3, address: 'Delhi' } }
Explanation:
The
deepCopy()
function recursively copies each property of thedog
object.Changes to the original
dog
object do not affectdogCopy
.
Example 3: Deep Copy Using Lodash’s Library _.cloneDeep()
Method
To use Lodash in your JavaScript project, you first need to install it. If you’re working in a Node.js environment or using package managers like npm or yarn, you can install Lodash with the following commands:
- Using npm:
npm install lodash
- Using yarn:
yarn install lodash
After installing Lodash, you can require it in your JavaScript file and start using its various utility functions, including _.cloneDeep()
for shallow copying.
const _ = require('lodash');
let dog = {
name: 'Tommy',
breed: 'Labrador',
details: {
age: 3,
address: 'Delhi'
}
};
// Creating a deep copy using lodash's cloneDeep()
let dogCopy = _.cloneDeep(dog);
// Modifying properties in the original object
dog.name = 'Charlie'; // Original object modified
dog.details.age = 4; // Nested object modified
console.log(dog); // { name: 'Charlie', breed: 'Labrador', details: { age: 4, address: 'Delhi' } }
console.log(dogCopy); // { name: 'Tommy', breed: 'Labrador', details: { age: 3, address: 'Delhi' } }
Explanation:
_.cloneDeep(dog)
creates a deep copy of thedog
object, including all nested properties.Changes to the original
dog
object do not affectdogCopy
.