JavaScript shallow copy and deep copy

This article shows the usages of shallow copy and deep copy in JavaScript. Most content is organized from MDN and some new content is added.

Shallow copy

In a shallow copy, the source and copy share the same reference properties.

In JavaScript, all standard built-in object-copy operations create shallow copies rather than deep copies:

Examples

// Shallow copy of an array via spread syntax

const objects = [{a: 1}, {b: 2}];
copy = [...objects];
console.log(copy[0] === objects[0]); // true

// Shallow copy of an object via speras syntax 

const obj = {id: 'a01', values: [101, 102]};
copy = {...obj};
console.log(copy.values === obj.values); // true

Deep copy

In a deep copy, the source and copy are completely independent.

For objects that are serializable, you can alternatively use the structuredClone() method to create deep copies.

Some examples that are not serializable

Calling JSON.stringify() to serialize the objects in those cases will fail. So there’s no way to make deep copies of such objects.

Examples

const objects = [{a: 1}, {b: 2}];

let copy = structuredClone(objects);
console.log(copy[0] === objects[0]); // false

Compatibility of structuredClone()

structuredClone() is a newly added function. Its compatibility on some main browsers:

  • Chrome v98

  • Firefox v94

  • Safari v15.4 (2022)

  • Safari iOS v15.4 (2022)

And it has lower availability in works. To add compatible structuredClone() support in all browsers, see Troubleshooting — StructuredClone is not defined.

Further reading

Reference

  • MDN: Shallow copy

  • MDN: Deep copy

  • MDN: structuredClone()

  • MDN: The structured clone algorithm

    It clones by recursing through the input object while maintaining a map of previously visited references, to avoid infinitely traversing cycles.

    Things that don’t work with structured clone

    • Function objects cannot be duplicated by the structured clone algorithm; attempting to throws a DataCloneError exception.
    • Cloning DOM nodes likewise throws a DataCloneError exception.
    • Certain object properties are not preserved:
    • The lastIndex property of RegExp objects is not preserved.
    • Property descriptors, setters, getters, and similar metadata-like features are not duplicated. For example, if an object is marked readonly with a property descriptor, it will be read/write in the duplicate, since that’s the default.
    • The prototype chain is not walked or duplicated.

    Note: Native Error types can be cloned in Chrome. Firefox can clone DOMException, and is working on the other error types.