Skip to main content

Difference between Shallow and Deep copy in JavaScript

00:02:45:90

Context

In this article, we will explain the difference between shallow and deep copies of objects in JavaScript and where to use them. First, it is important to understand that data values in JavaScript are stored in two forms: Primitives (Boolean, Null, Undefined, String, Number, BigInt, and Symbol), which are immutable, and Objects (object literals, arrays, dates, etc.), which are mutable. Since objects are mutable, certain methods can alter them. Objects are copied by reference, meaning that changing the copied object might also alter the original object.

Example with Primitives:

javascript
const testCase = 'TestCase';
testCase[0] = 'B';

console.log(testCase);
// Output: "TestCase"

From the example above, we see that the first letter of testCase didn't change. While this is allowed in non-strict mode, if we enable strict mode, we get an error:

javascript
'use strict';
const testCase = 'TestCase';
testCase[0] = 'B';

console.log(testCase);
// Uncaught TypeError: Cannot assign to read only property '0' of string 'TestCase'

Here is an example that proves that objects are mutable:

javascript
const testCase = ['T', 'e', 's', 't'];
testCase[0] = 'B';

console.log(testCase);
// Output: ["B", "e", "s", "t"]

Difference Between Shallow and Deep Copy

Shallow Copy

A shallow copy creates a new object but only copies the reference of nested objects. If the original object contains other objects, only their references are copied, not the actual nested objects.

Example

Using Object.assign or the spread operator (...) creates a shallow copy:

javascript
const original = { name: 'Kastriot', address: { city: 'Vienna' } };
const shallowCopy = { ...original };
shallowCopy.address.city = 'Berlin';
console.log(original.address.city);
// Output: "Berlin"

Deep Copy

A deep copy creates a new object and recursively copies all nested objects, ensuring complete duplication of the original object. Changes to the deep copy do not affect the original object.

Example

Using libraries like lodash or JSON.parse(JSON.stringify()) and recursive functions can achieve deep copying.

javascript
const _ = require('lodash');
const original = { name: 'Kastriot', address: { city: 'Vienna' } };
const deepCopy = _.cloneDeep(original);
deepCopy.address.city = 'Berlin';
console.log(original.address.city);
// Output: "Vienna"

Update (20-10-2024): You can make deep copy naivly using structuredClone()

Since March 2022 structuredClone() method is available in JavaScript. It is a deep copy method that can be used to clone objects, arrays, and other data types. It is a more efficient and reliable way to create deep copies of objects.

javascript
const original = { name: 'Kastriot', address: { city: 'Vienna' } };
const deepCopy = structuredClone(original);
deepCopy.address.city = 'Berlin';
console.log(original.address.city);
// Output: "Vienna"

You can read more about structuredClone() here.

Use Cases

  • Shallow Copy: Suitable for simple objects or when only top-level properties need duplication.
  • Deep Copy: Necessary for complex objects with nested structures to ensure complete independence from the original object.

Performance

  • Shallow Copy: Faster and less resource-intensive.
  • Deep Copy: Slower and more resource-intensive due to recursive copying.

Conclusion

Understanding the differences between shallow and deep copies is crucial for effectively managing and manipulating objects in JavaScript. By choosing the appropriate copy method, you can optimize performance and ensure the integrity of your data. Whether you need a quick, shallow copy or a thorough, deep copy, JavaScript provides the tools to meet your needs.


Photo by Ralph Mayhew on Unsplash

Newesletter
Subscribe to get monthly updates with new articles