Copy Objects Ways in JavaScript
Fatemeh Paghar

Fatemeh Paghar @fpaghar

About: Programming is a major entertainment of my life. I’m interested in learning new technology development concepts and making suggestions for improvement. GitHub: https://github.com/paghar

Location:
Germany
Joined:
Dec 11, 2022

Copy Objects Ways in JavaScript

Publish Date: Mar 16 '24
73 19

To copy objects in JavaScript, you typically have three options: using the assignment operator (=) for reference copying, performing a shallow copy using methods like Object.assign() or the spread operator (...), and creating a deep copy using a combination of JSON.parse() and JSON.stringify().

1. Reference Copy (Assignment Operator =):

const originalObject = { key: 'value' };
const referenceCopy = originalObject;
Enter fullscreen mode Exit fullscreen mode

In this method, referenceCopy now points to the same object as originalObject. Changes made to one will affect the other.This method creates a reference to the original object. Changes made to the original object will be reflected in the copied object, and vice versa. This is not a true copy; rather, both variables point to the same object.

2. Shallow Copy:

a. Using Object.assign():

const originalObject = { key: 'value' };
const shallowCopy = Object.assign({}, originalObject);
Enter fullscreen mode Exit fullscreen mode

Object.assign() creates a shallow copy of the object. It copies the enumerable properties from one or more source objects to a target object. In the example above, an empty object {} serves as the target, and originalObject is the source. Note that nested objects are still referenced, so changes to nested objects in the original will affect the copied object.

b. Using Spread Operator (...):

const originalObject = { key: 'value' };
const shallowCopy = { ...originalObject };
Enter fullscreen mode Exit fullscreen mode

The spread operator is a concise way to create shallow copies of objects. Like Object.assign(), it only creates a copy of the top-level properties. Nested objects are still referenced, so changes to nested objects in the original will affect the copied object.

Both of these methods create a shallow copy, copying only the top-level properties of the object. Changes to nested objects will be reflected in both the original and the copy.

3. Deep Copy:

Using JSON.parse() and JSON.stringify()

const originalObject = { key: 'value', nested: { key2: 'value2' } };

// Using JSON.parse() and JSON.stringify()
const deepCopy = JSON.parse(JSON.stringify(originalObject));

Enter fullscreen mode Exit fullscreen mode

This method creates a deep copy of the object, including nested structures. Keep in mind that this approach has limitations, such as not preserving non-JSON-safe data and being less efficient for large or complex objects.

Select the suitable approach depending on your particular circumstances:

  • Reference Copy (=): Use when you want both variables to reference the same object.
  • Shallow Copy (Object.assign() or Spread Operator): Use when you need a copy of the top-level properties and are not concerned about nested objects being shared.
  • Deep Copy (JSON.parse() and JSON.stringify()): Use when you need a completely independent copy, including nested structures. Be cautious about limitations with non-JSON-safe data.

A glance at examples

// Shallow Copy Example
let product = {
    id: 1,
    name: 'Smartphone',
    price: 499.99,
    details: {
        brand: 'TechCo',
        model: 'SmartX1',
        specifications: {
            display: '6.2 inches',
            camera: '12 MP',
            storage: '64 GB'
        }
    }
};

// Shallow copy using the spread operator
let copiedProduct = { ...product };

copiedProduct.name = 'Smartwatch'; // Disconnected

// Changes in the nested object are connected
copiedProduct.details.model = 'WatchPro';
copiedProduct.details.specifications.display = '1.3 inches';

console.log("Shallow Copy - Copied Product:", copiedProduct);
console.log("Shallow Copy - Original Product:", product);

// Deep Copy Example
let productDeep = {
    id: 1,
    name: 'Smartphone',
    price: 499.99,
    details: {
        brand: 'TechCo',
        model: 'SmartX1',
        specifications: {
            display: '6.2 inches',
            camera: '12 MP',
            storage: '64 GB'
        }
    }
};

// Deep copy using JSON methods
let copiedProductDeep = JSON.parse(JSON.stringify(productDeep));

copiedProductDeep.name = 'Laptop'; // Disconnected

// Changes in the nested object are also disconnected
copiedProductDeep.details.model = 'LaptopPro';
copiedProductDeep.details.specifications.display = '15.6 inches';

console.log("Deep Copy - Copied Product:", copiedProductDeep);
console.log("Deep Copy - Original Product:", productDeep);

Enter fullscreen mode Exit fullscreen mode

Reference:

Comments 19 total

  • Jon Randy 🎖️
    Jon Randy 🎖️Mar 16, 2024

    You missed structuredClone.

    • Fatemeh Paghar
      Fatemeh PagharMar 16, 2024

      In JavaScript, the structuredClone() method is used to create a deep copy of a JavaScript object, including nested objects and arrays. This method is similar to JSON.parse(JSON.stringify(object)), but it can handle more complex data types such as Date, RegExp, Map, Set, and cyclic object references, which are not supported by JSON.stringify().

      const originalObject = {
        name: 'John',
        age: 30,
        hobbies: ['reading', 'hiking'],
        address: {
          city: 'New York',
          country: 'USA'
        }
      };
      
      // Create a deep copy of the original object
      const clonedObject = structuredClone(originalObject);
      
      console.log(clonedObject);
      
      
      Enter fullscreen mode Exit fullscreen mode
    • Victor Zamanian
      Victor ZamanianMar 17, 2024

      Honestly very odd that this isn't edited in the main article as the main option now. It should completely replace the JSON.stringify dance. That can be completely forgotten for this purpose. Not for serialization of course, but in this context it shouldn't be recommended anymore.

      • Mike Talbot ⭐
        Mike Talbot ⭐Mar 18, 2024

        I abandoned it because it's way slower. It has some useful other capabilities, but I find I don't need them. In my tests, structured clone was way too slow.

        • Victor Zamanian
          Victor ZamanianMar 20, 2024

          Structured clone is way slower than stringify? I mean it should be somewhat slower because it's more complete and has more logic. How much we talking? A benchmark coverage would be interesting to read. 👍

          • Mike Talbot ⭐
            Mike Talbot ⭐Mar 20, 2024

            Jon and I linked benchmarks in other comments. For me it is between 42% and 45% slower. I copy a decent number of simple objects, 1/2 the speed is impactful. I do have cases with circular references etc., these are a reasonable candidate for structured clone, I find that an adapted stringify is more handy though, I can then store things and restore them from persistent storage.

            Mine, Jon's

    • J.M. Cléry
      J.M. CléryMar 18, 2024

      ⚠️ Moreover JSON.parse and stringify are very bad for performance. (Incorrect. See discussion below)

      Totally agree with the first comments that structuredClone should be the only way in modern codebases to deep clone objects. If you need alternatives, you can use libraries for that (e.g. _.cloneDeep())

      • Mike Talbot ⭐
        Mike Talbot ⭐Mar 18, 2024

        Are you sure? Last time I checked structuredClone was dramatically slower than parse and stringify.

        measurethat.net/Benchmarks/Show/18...

        • Jon Randy 🎖️
          Jon Randy 🎖️Mar 19, 2024

          Yup, structuredClone does seem much slower.

          • J.M. Cléry
            J.M. CléryMar 19, 2024

            You are correct, I'm sorry (comment above edited).
            I remembered a discussion where I heard that JSON.stringify was significantly a slow approach to deep clone objects. That misled me doing the comparison with structuredClone.
            Thank you for the rectification.

            • Mike Talbot ⭐
              Mike Talbot ⭐Mar 19, 2024

              Same thing bit me, I presumed it would be faster and wasted a couple of days refactoring some things (across workers etc) ended up with the "dance" just being way faster, even coping with circular references etc. Frustrating and I was pretty surprised.

      • Hauke T.
        Hauke T.Mar 20, 2024

        Performance of JSON.parse(JSON.stringify(obj)) vs. structuredClone(obj) depends on the kind of data you want to clone.

        While for more (almost) shallow data the JSON approach is faster, for deeply nested data structuredClone(obj) becomes more performant:

        measurethat.net/Benchmarks/Show/30...

        The test is very deeply nested, but plausible.

        As annoying as this is - there is no silver bullet (performance-wise).
        You need to know what kind of data your application will handle, you need to test your solution based on your knowledge about the target audience and their hardware.

        • Mahmoud Abdel Mohsen
          Mahmoud Abdel MohsenMar 28, 2024

          I guess you are right @htho , structuredClone(obj) seems faster in almost all cases unless the data was utterly nested (an edge case).

          However, for edge cases I wouldn't use JSON.parse(JSON.stringify(obj)) either. I'd rather stay with structuredClone(obj) for a safer copy option.

          jsbm 100 copies
          jsbm 1 copy

  • Nicholasbalette
    NicholasbaletteMar 18, 2024

    Refreshing

  • João Angelo
    João AngeloMar 19, 2024

    Hi Fatemeh Paghar,
    Your tips are very useful
    Thanks for sharing

  • Hoon Kang
    Hoon KangMar 27, 2024

    Thank you for all the posts and discussions! While I was already familiar with shallow copying an object, I hadn't known about creating deep copies until now. I've learned several approaches, along with their pros and cons.
    Your post is a lot helpful! 👍🏻

  • Nguyen Xuan hoa
    Nguyen Xuan hoaApr 5, 2024

    With nested object, we can use recursion and Object.assign() or Spread Operator to make deep copy too :)

  • Adya Kalhari
    Adya KalhariAug 5, 2024

    This is a great article on the different ways to copy objects in JavaScript! I particularly liked the explanation of reference copies, shallow copies, and deep copies. I also found the comparison of JSON.parse() and JSON.stringify() with structuredClone() to be very informative.

    Here's a link to my blog post on object copying in JavaScript, which goes into more detail here.

    I hope this is helpful!

  • Islam
    IslamAug 10, 2024

    The overall pros of JSON.parse performance wise is that the runtime ready to deal with that better since the JSON like structure is a well-suitable and "recognizable" for the runtime and underlying mechanisms of working with it are nicely optimized.

Add comment