1. Shallow Copy
A shallow copy creates a new object or array but does not recursively copy the nested objects/arrays inside it. Instead, the references to the nested objects are copied, so changes to nested objects affect both the original and the copied objects.
In this process, only the top-level properties are copied, while nested objects or arrays still reference the original memory location. This means that if you change the nested properties in one object, those changes will reflect in the other because they share the same memory reference.
Example 1: Shallow Copy using Object.assign():
// Original Object
const original = {
name: "John",
age: 30,
address: {
city: "New York",
zip: "10001"
}
};
// Shallow copy using Object.assign()
const shallowCopy = Object.assign({}, original);
// Modify the nested object in the shallow copy
shallowCopy.address.city = "Los Angeles";
console.log(original.address.city); // Output: "Los Angeles"
console.log(shallowCopy.address.city); // Output: "Los Angeles"
console.log(original); // Output: {name: 'John', age: 30, address: {city: 'Los Angeles', zip: '10001'}}
console.log(shallowCopy); // Output: {name: 'John', age: 30, address: {city: 'Los Angeles', zip: '10001'}}
Explanation: In the above example:
-
original
is an object with a nested object address. -
shallowCopy
is created usingObject.assign()
, which copies only the first level of properties fromoriginal
toshallowCopy
. - However, since
address
is a reference to the same object in bothoriginal
andshallowCopy
, modifyingshallowCopy.address
affects both objects.
Example 2: Shallow Copy using the Spread Operator
// Original object
const book = {
title: 'JavaScript Guide',
author: 'John Doe',
publisher: {
name: 'Tech Books',
year: 2020
}
};
// Shallow copy using the spread operator
const bookCopy = { ...book };
// Modify the nested object in the copied object
bookCopy.publisher.year = 2023;
console.log(book.publisher.year); // Output: 2023 (affected)
console.log(bookCopy.publisher.year); // Output: 2023
Explanation:
The spread operator ({...book})
creates a shallow copy of the object. However, since publisher
is a nested object, both the original and the copied object share the same reference for the publisher
object.
Example 3: Shallow Copy with Arrays using the Spread Operator
// Original array
const colors = ['red', 'green', 'blue'];
// Shallow copy using the spread operator
const colorsCopy = [...colors];
// Modify an element in the copied array
colorsCopy[0] = 'yellow';
console.log(colors); // Output: ['red', 'green', 'blue']
console.log(colorsCopy); // Output: ['yellow', 'green', 'blue']
Explanation:
In this case, the spread operator creates a shallow copy of the array. Since the array doesn't contain any nested objects or arrays, changes to the copied array donβt affect the original.
Example 4: Shallow Copy with Arrays using Slice
// Original array
const numbers = [1, 2, [3, 4]];
// Shallow copy using slice method
const numbersCopy = numbers.slice();
// Modify the nested array in the copied array
numbersCopy[2][0] = 99;
numbersCopy[1] = 12
console.log(numbers); // Output: [1, 2, [99, 4]
console.log(numbersCopy); // Output: [1, 12, [99, 4]
Explanation:
- The shallow copy with
.slice()
only copied the references for the nested arrays. - Modifying the nested array
(numbersCopy[2][0] = 99)
affected bothnumbers
andnumbersCopy
because they share the same reference to the nested array. - Modifying a non-nested element (numbersCopy[1] = 12) only affected
numbersCopy
, notnumbers
, because it is a primitive value (non-reference type).
Thus, the shallow copy mechanism with
.slice()
works at the top level for the array but does not fully isolate nested objects or arrays.
Example 5: Shallow Copy with Objects Containing Arrays
const config = {
theme: 'dark',
colors: ['red', 'green'],
};
// Shallow copy using Object.assign()
const configCopy = Object.assign({}, config);
// Modify the array in the copied object
configCopy.colors[0] = 'yellow';
config.theme = "light"
console.log(config); // Output: {theme: 'light', colors: ['yellow', 'green']}
console.log(configCopy); // Output: {theme: 'dark', colors: ['yellow', 'green']}
Explanation:
-
configCopy.theme
remains 'dark' becausetheme
is a primitive, and the shallow copy copied the value, not the reference. -
configCopy.colors
still points to the array ['yellow', 'green'], but this change was due to the shared reference betweenconfig
andconfigCopy
(they both point to the same array). -
Shallow copy
means that the top-level properties are copied, but for reference types (arrays, objects), only the reference is copied, not the actual values.
Example 6: Shallow Copy with Arrays Containing Objects
// Original array containing objects
const products = [
{ name: 'Laptop', price: 1000 },
{ name: 'Phone', price: 500 }
];
// Shallow copy using slice
const productsCopy = products.slice();
// Modify the object in the copied array
productsCopy[0].price = 1200;
console.log(products[0]); // Output: {name: 'Laptop', price: 1200}
console.log(productsCopy[0]); // Output: {name: 'Laptop', price: 1200}
Explanation:
Since the products
array contains objects, and slice() creates a shallow copy, both products
and productsCopy
refer to the same object for each element in the array. Changing the price
in the copied array also affects the original
array.
2.Deep Copy
A Deep Copy
creates a completely independent copy of the object, and recursively copies all nested objects and arrays, meaning that changes to the deep copy will not affect the original object and vice versa. This ensures that changes made to one object do not affect the others. Each object is stored in a separate memory location, making them entirely independent.
Example:
// Original Object
const original = {
name: "John",
age: 30,
address: {
city: "New York",
zip: "10001"
}
};
// Deep copy using JSON methods
const deepCopy = JSON.parse(JSON.stringify(original));
// Modify the nested object in the deep copy
deepCopy.address.city = "Los Angeles";
console.log(original.address.city); // Output: "New York"
console.log(deepCopy.address.city); // Output: "Los Angeles"
Explanation:
- JSON.stringify() converts the object into a JSON string.
- JSON.parse() parses the string back into a new object.
- This creates a new, independent object where all nested objects are copied, and any modifications to the deep copy do not affect the original object.
Important Differences:
Deep Copy with Arrays:
// Original Array
const originalArray = [1, 2, [3, 4]];
// Deep copy using JSON methods
const deepCopyArray = JSON.parse(JSON.stringify(originalArray));
// Modify the nested array
deepCopyArray[2][0] = 99;
deepCopyArray[1] = 12
console.log(originalArray); // Output: [1, 2, [3, 4]
console.log(deepCopyArray); // Output: [1, 12, [99, 4]
Explanation:
const deepCopyArray = JSON.parse(JSON.stringify(originalArray));
JSON.stringify(originalArray):
- This converts the entire
originalArray
into a JSON string. The nested array [3, 4] is also converted to its JSON representation (a string representation).
JSON.parse():
- The
JSON.parse()
method takes the JSON string and converts it back into a newobject or array
. - The key point here is that
nested objects (like the array [3, 4])
are also deep-copied, not just the top-level array. - As a result,
deepCopyArray
is an entirely new array with anew reference
, and the nested array [3, 4] is also anew reference
indeepCopyArray
. This is the key difference between deep copy and shallow copy.
deepCopyArray[2][0] = 99;
- Here,
deepCopyArray[2]
refers to the nested array[3, 4]
, which is a new, independent array from the one inoriginalArray
. - We change the first element of this nested array to
99
. This does not affectoriginalArray
because the nested arrays aredeeply copied
.
originalArray: [1, 2, [3, 4]]
- This remains unchanged because we performed a
deep copy
, meaning the original array and the copied array are completely independent, including their nested arrays.
deepCopyArray: [1, 12, [99, 4]]
- This reflects the changes we made:
- The second element was changed from 2 to 12.
- The first element of the nested array was changed from 3 to 99.
Caveats:
- Using
JSON.parse(JSON.stringify())
for deep copying has limitations: - It cannot copy functions,
undefined
,RegExp
,Date
, or circular references. - It might not preserve special object types (e.g.,
Map
,Set
, orDate
).
For these cases, libraries like Lodash
provide more robust deep copying utilities (e.g., _.cloneDeep())
, which handle these edge cases more gracefully.
-
Shallow Copy
is faster but links to nested objects, meaning changes to nested structures will reflect in both the original and the copy. -
Deep Copy
is slower but creates a fully independent copy, including all nested objects, which makes it more suitable when you need complete isolation between the original and the copied object.
Top comments (0)