What is the most efficient way to deep clone an object in JavaScript?

What is the most efficient way to deep clone an object in JavaScript?

Problem Statement

JSON serialization method is one of the simplest and most commonly used ways to deep-clone an object in JavaScript but what is the most efficient way to clone an object in JavaScript?

Example:

const original = { a: 1, b: { c: 2 } };
const cloned = JSON.parse(JSON.stringify(original));
console.log(cloned); 

// Output: 
// { a: 1, b: { c: 2 } } 

Fast cloning, easy to use, works in older environments but with data loss. Data loss means certain types of data (like functions, undefined, Symbol, or custom class instances) are omitted or transformed during the cloning process.


Solution Code

In modern JavaScript, structuredClone is a built-in function designed for deep cloning.

const original = { a: 1, b: { c: 2 } };
const cloned = structuredClone(original);

console.log(cloned); 
console.log(original === cloned); 

// Output:
//  { a: 1, b: { c: 2 } }
// false

structuredClone is the modern and fast way to deep clone objects. It supports various types, including objects, arrays, etc.


Learn More

Here are the other ways to deep clone objects with examples:


Using a Library (e.g., Lodash's cloneDeep)

Lodash provides a robust method for deep cloning:

import _ from 'lodash';

const original = { a: 1, b: { c: 2 } };
const cloned = _.cloneDeep(original);
console.log(cloned); 

// Output:
//  { a: 1, b: { c: 2 } }

How It Works:

  • Deep Traversal: Lodash’s cloneDeep recursively traverses the entire object, including nested structures, arrays, and special types.
  • Preserves Object Integrity:
    • Retains all object types (Date, Set, Map, etc.).
    • Ensures no references are shared between the original and cloned objects.

Custom Recursive Function

We can write a recursive function for deep cloning:

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;

  if (Array.isArray(obj)) {
    return obj.map(deepClone);
  }

  const clonedObj = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clonedObj[key] = deepClone(obj[key]);
    }
  }
  return clonedObj;
}

const original = { a: 1, b: { c: 2 } };
const cloned = deepClone(original);

console.log(cloned); 

// Output:
//  { a: 1, b: { c: 2 } }

How It Works:

  • Base Case: If the input (obj) is null or not an object, return it directly (handles primitives and null).
  • Handle Arrays: If obj is an array, use .map() to recursively clone each element.
  • Handle Objects: Create an empty object, iterate through its keys, and recursively clone each property.
  • Return Cloned Object: Ensures the cloned structure is completely independent of the original.

Comparison with Other Methods

Method Handles Special Types Handles Circular References Performance Ease of Use
structuredClone Yes Yes Fast Easy
JSON.stringify No No Moderate Very Easy
_.cloneDeep Yes Yes Moderate Easy

If you need robust, versatile deep cloning, Lodash's cloneDeep is an excellent choice!


Summary

  • For modern applications, structuredClone is the fastest and most robust option.
  • For complex scenarios involving circular references and special types, Lodash's cloneDeep is the best choice.
  • For simple cases, JSON.parse(JSON.stringify()) remains a quick solution, though it has limitations.

References


Summary

Thank you for taking the time to read through this article on deep cloning in JavaScript! We hope that you now have a solid understanding of the most efficient methods to clone objects, such as structuredClone, JSON.parse(JSON.stringify()), and _.cloneDeep. By incorporating these techniques, you can better manage data structures and optimize your code for different scenarios.

As you continue to explore JavaScript, we recommend diving deeper into the following additional topics:

  1. Handling Circular References – Learn how to deal with circular references that might lead to infinite loops in your deep cloning operations.
  2. Performance Optimization – Discover benchmarking techniques to compare the cloning methods and optimize performance in large-scale applications.
  3. Special Data Types – Understand how to handle non-JSON serializable data types like Date, RegExp, Map, and Set during the cloning process.
  4. Custom Cloning Functions – Explore how to write custom recursive functions for deep cloning to suit complex data structures.
  5. Security Considerations – Stay aware of potential security risks when cloning objects from untrusted sources (e.g., prototype pollution and function cloning).
  6. Polyfills for Older Browsers – Find out how to make structuredClone work in older environments using polyfills.

As you implement these techniques, remember that JavaScript is constantly evolving, and staying up-to-date with modern practices will keep your coding skills sharp. With knowledge of deep cloning and its nuances, you’re now equipped to tackle more complex JavaScript challenges. Keep experimenting, learning, and pushing the boundaries of what you can achieve with JavaScript!

Stay curious, keep coding, and make the most of your newfound knowledge. Happy coding!


Compiled by team Crio.Do

You've successfully subscribed to Crio Blog
Great! Next, complete checkout to get full access to all premium content.
Welcome back! You've successfully signed in.
Unable to sign you in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Billing info update failed.