NeuroAgent

Complete Guide to Cloning JavaScript Objects

Learn the modern methods to create independent JavaScript object copies. Discover structuredClone(), deep vs shallow copy techniques, and best practices for truly cloned objects.

Question

How do I correctly clone a JavaScript object to create an independent copy?

I have an object x and want to create a copy called y where modifications to y don’t affect the original x. I understand that copying objects derived from built-in JavaScript objects can introduce unwanted properties, but this isn’t a concern for my use case since I’m working with custom literal-constructed objects. What’s the proper method to clone a JavaScript object in this scenario?

NeuroAgent

Creating an independent copy of a JavaScript object requires using proper deep copy techniques to ensure that modifications to the cloned object don’t affect the original. For custom literal-constructed objects, the modern approach is to use the structuredClone() method, which creates a true deep copy while handling nested objects, circular references, and special JavaScript types properly.

Contents

Understanding Shallow vs Deep Copy

The fundamental difference between shallow and deep copy lies in how they handle nested objects and references.

A shallow copy creates a new object and copies all enumerable own properties from the original object to the new object. However, for nested objects or arrays, it only copies the references, not the actual values. This means that when you modify a nested property in the copied object, it affects the original object as well source.

A deep copy, on the other hand, recursively clones all nested objects and arrays, creating completely independent copies at every level. This ensures that modifications to any part of the cloned object won’t affect the original source.

Key Insight: When working with custom literal-constructed objects that contain nested properties, you always need a deep copy to achieve true independence between the original and cloned objects.

Modern Solution: structuredClone()

The structuredClone() function, introduced in 2022, is the modern and recommended way to create deep copies of JavaScript objects. This method provides a true deep copy while automatically handling complex scenarios like circular references and special JavaScript types.

javascript
const original = {
  name: "John",
  age: 30,
  address: {
    city: "New York",
    zip: "10001"
  },
  hobbies: ["reading", "coding"]
};

// Create a deep copy using structuredClone()
const deepCopy = structuredClone(original);

// Modify the copy
deepCopy.address.city = "Boston";
deepCopy.hobbies.push("swimming");

// Original remains unchanged
console.log(original.address.city); // "New York"
console.log(original.hobbies); // ["reading", "coding"]

Key advantages of structuredClone():

  • Automatic handling of circular references: Unlike JSON methods, it can handle objects that reference themselves
  • Preservation of special types: Maintains Date, Map, Set, RegExp, and other built-in types
  • Transferable objects: Supports cloning objects that can be transferred between different contexts like Web Workers source
  • Native implementation: No external libraries required
javascript
// Example with circular reference
const circularObj = {};
circularObj.self = circularObj;

// This works with structuredClone()
const clone = structuredClone(circularObj);
console.log(clone.self === clone); // true (preserves circular reference)

// This would fail with JSON methods
try {
  JSON.parse(JSON.stringify(circularObj)); // Throws TypeError
} catch (error) {
  console.log("JSON method error:", error.message);
}

Alternative Deep Copy Methods

While structuredClone() is recommended, there are other deep copy methods you might encounter or need to use in certain scenarios.

JSON.stringify() + JSON.parse()

This is a common workaround for deep copying, but it has significant limitations:

javascript
const original = { name: "John", details: { age: 30 } };
const deepCopy = JSON.parse(JSON.stringify(original));

Limitations:

  • ❌ Fails with circular references (throws TypeError)
  • ❌ Loses special types like Date, Map, Set, RegExp (converts them to plain objects)
  • ❌ Ignores undefined values, functions, and symbols
  • ❌ Can be significantly slower than structuredClone() source

Lodash cloneDeep()

For projects already using Lodash, the cloneDeep() method provides a reliable deep copy solution:

javascript
const _ = require('lodash');
const deepCopy = _.cloneDeep(original);

Advantages:

  • ✅ Handles circular references
  • ✅ Preserves special types and functions
  • ✅ Well-tested and widely used
  • ✅ Works in all JavaScript environments

Disadvantages:

  • ❌ Adds external dependency to your project
  • ❌ Larger bundle size compared to native solutions

Custom Deep Copy Function

For specific use cases, you can implement a custom deep copy function:

javascript
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof Array) return obj.map(item => deepClone(item));
  
  const cloned = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloned[key] = deepClone(obj[key]);
    }
  }
  return cloned;
}

Shallow Copy Methods

For completeness, here are the common shallow copy methods, though they’re not suitable for creating truly independent copies when nested objects are involved:

Spread Operator

javascript
const shallowCopy = { ...original };

Object.assign()

javascript
const shallowCopy = Object.assign({}, original);

Array Methods (for arrays)

javascript
const shallowCopy = original.slice();
const shallowCopy2 = [...original];

Important: These methods only create shallow copies. If your object contains nested objects or arrays, modifying those nested properties in the copy will affect the original object source.

Practical Examples and Best Practices

Basic Object Deep Copy

javascript
const user = {
  id: 1,
  profile: {
    name: "Alice",
    preferences: {
      theme: "dark",
      notifications: true
    }
  },
  settings: {
    language: "en-US",
    timezone: "UTC"
  }
};

// Best practice: Use structuredClone()
const userClone = structuredClone(user);

// Now you can safely modify clone
userClone.profile.preferences.theme = "light";
userClone.settings.language = "es-ES";

// Original remains untouched
console.log(user.profile.preferences.theme); // "dark"
console.log(user.settings.language); // "en-US"

Handling Complex Objects

javascript
const complexObj = {
  date: new Date(),
  map: new Map([['key', 'value']]),
  set: new Set([1, 2, 3]),
  regex: /test/g,
  circular: null
};

// Create circular reference
complexObj.circular = complexObj;

// structuredClone handles all this correctly
const clone = structuredClone(complexObj);

console.log(clone.date instanceof Date); // true
console.log(clone.map instanceof Map); // true
console.log(clone.set instanceof Set); // true
console.log(clone.regex instanceof RegExp); // true
console.log(clone.circular === clone); // true (circular reference preserved)

Performance Comparison

Here’s a quick performance comparison for different deep copy methods:

Method Speed Circular References Special Types Dependencies
structuredClone() ⭐⭐⭐⭐⭐ None
JSON.stringify + parse ⭐⭐ None
Lodash cloneDeep() ⭐⭐⭐ Lodash
Custom function ⭐⭐⭐ ⭐ (custom) None

Performance Considerations

When working with large or deeply nested objects, performance becomes an important consideration:

  • structuredClone() is generally the fastest native method for deep copying
  • For very large objects, consider if you really need a full deep copy or if selective copying would suffice
  • The structuredClone() method is optimized by JavaScript engines and typically outperforms JSON-based approaches by 10-20% source

Sources

  1. Deep copy - MDN Web Docs
  2. Deep Copy vs Shallow Copy in JavaScript - Mastering JS
  3. Window: structuredClone() method - Web APIs | MDN
  4. 3 Ways to Copy objects in JavaScript, Shallow vs. Deep Copy - JavaScript Tutorial
  5. The Power of structuredClone(): A Comprehensive Guide to Deep Cloning in JavaScript
  6. Deep Cloning in JavaScript: The Modern Way. Use structuredClone
  7. What is the most efficient way to deep clone an object in JavaScript? - Stack Overflow
  8. Deep-copying in JavaScript using structuredClone - web.dev

Conclusion

  • Use structuredClone() for modern JavaScript deep copying - it’s the most reliable, efficient, and comprehensive solution introduced in 2022
  • Avoid shallow copies when you need independent copies of nested objects and arrays
  • Consider alternatives like Lodash’s cloneDeep() only if you’re already using Lodash or need compatibility with older browsers
  • Test your copies to ensure they’re truly independent by modifying nested properties and verifying the original remains unchanged
  • Remember performance when dealing with large objects - structuredClone() is optimized and generally the fastest native option

For your use case with custom literal-constructed objects, structuredClone() provides the perfect balance of simplicity, reliability, and performance for creating truly independent object copies.