Back to all articles
JavaScript

structuredClone: A New Approach to Object Cloning in JavaScript

The structuredClone() function is a recent addition to JavaScript that provides a superior method for creating deep copies of objects. It handles a wide range of data types and offers notable advantages over previous methods like JSON.parse() / JSON.stringify() and the spread operator. Its capacity to clone complex nested objects without shared references ensures truly independent copies, enhancing code efficiency and reliability.

How structuredClone Differs From JSON.parse / JSON.stringify

While JSON.parse() and JSON.stringify() have been historically used to create a deep copy of an object, they come with certain limitations. For instance, they don't work well with objects containing functions, Date objects, undefined, Infinity, or NaN. Furthermore, they are unable to handle complex JavaScript objects like Map, Set, or ArrayBuffer.

Here is a demonstration of the problem with cloning a Date object using JSON.parse / JSON.stringify:

// Creating a Date object
let original = { a: 1, b: { c: new Date() } }

// Cloning with JSON.parse / JSON.stringify
let copyJson = JSON.parse(JSON.stringify(original))

console.log(copyJson.b.c instanceof Date)
// outputs: false

As you can see, JSON.parse / JSON.stringify converts the Date object into a string, failing to properly clone it.

structuredClone(), on the other hand, can handle a wide range of JavaScript's built-in types, including:

  • All primitive types
  • Object and Array
  • Map, Set
  • Blob and File
  • and more...

n fact, the only objects structuredClone() cannot clone are Error objects and functions.

How structuredClone Differs From the Spread Operator

The spread operator (...) is another popular method for cloning JavaScript objects. However, this operator only performs a shallow copy, copying the object's top layer and sharing references for any nested objects. This can lead to unexpected behavior when nested properties are modified.

Here is a demonstration of the problem with cloning a Date object using the spread operator:

// Cloning with the spread operator
let copySpread = { ...original }

console.log(copySpread.b.c instanceof Date) // outputs: true
copySpread.b.c.setFullYear(2030)

console.log(original.b.c.getFullYear())
// outputs: 2030, because it shares the reference

As shown, the spread operator clones the Date object but it shares the same reference with the original Date object, implying that modifications to the copied object affect the original one.

But with structuredClone(), the story is different:

// Cloning with structuredClone
let copyClone = structuredClone(original)
console.log(copyClone.b.c instanceof Date) // outputs: true

copyClone.b.c.setFullYear(2030)
console.log(original.b.c.getFullYear())
// outputs: 2023, it does not share the reference

The structuredClone() function correctly clones the Date object and does not share the reference, ensuring that modifications to the copied object do not affect the original one.

Conclusion

In summary, the structuredClone() function represents a significant improvement over previous methods for object cloning in JavaScript. It offers robust deep cloning capabilities, capable of handling a variety of data types, which gives it an edge over traditional methods such as JSON.parse() / JSON.stringify() and the spread operator. Another solution might be the function from lodash _.cloneDeep.