Live Demo 👉 All Demo, No Pitch: Content & Commerce / Builder.io & Elastic Path on 12/13
Use Cases
Pricing
Blog
×
Visual CMS
Drag-and-drop visual editor and headless CMS for any tech stack
Theme Studio for Shopify
Build and optimize your Shopify-hosted storefront, no coding required
Resources
Blog
Get StartedLogin☰
Did you know, there's now a native way in JavaScript to do deep copies of objects?
That's right, this structuredClone
function is built into the JavaScript runtime:
Did you notice in the example above we not only copied the object, but also the nested array, and even the Date object?
And all works precisely as expected:
That’s right, structuredClone
can not only do the above, but additionally:
Date
, Set
, Map
, Error
, RegExp
, ArrayBuffer
, Blob
, File
, ImageData
, and many moreSo for example, this madness would even work as expected:
It is important to note we are talking about a deep copy. If you just need to do a shallow copy, aka a copy that does not copy nested objects or arrays, then we can just do an object spread:
Or even one of these, if you prefer
But as soon as we have nested items, we run into trouble:
As you can see, we did not make a full copy of this object.
The nested date and array are still a shared reference between both, which can cause us major issues if we want to edit those thinking we are only updating the copied calendar event object.
JSON.parse(JSON.stringify(x))
?Ah yes, this trick. It is actually a great one, and is surprisingly performant, but has some shortcomings that structuredClone
addresses.
Take this as an example:
If we log problematicCopy
, we would get:
That’s not what we wanted! date
is supposed to be a Date
object, not a string.
This happened because JSON.stringify
can only handle basic objects, arrays, and primitives. Any other type can be handled in hard to predict ways. For instance, Dates are converted to a string. But a Set
is simply converted to {}
.
JSON.stringify
even completely ignores certain things, like undefined
or functions.
For instance, if we copied our kitchenSink
example with this method:
We would get:
Ew!
Oh yeah, and we had to remove the circular reference we originally had for this, as JSON.stringify
simply throws errors if it encounters one of those.
So while this method can be great if our requirements fit what it can do, there is a lot that we can do with structuredClone
(aka everything above that we failed to do here) that this method cannot.
_.cloneDeep
?To date, Lodash’s cloneDeep
function has been a very common solution to this problem.
And this does, in fact, work as expected:
But, there is just one caveat here. According to the Import Cost extension in my IDE, that prints the kb cost of anything I import, this one function comes in at a whole 17.4kb minified (5.3kb gzipped):
And that assumes you import just that function. If you instead import the more common way, not realizing that tree shaking doesn’t always work the way you hoped, you could accidentally import up to 25kb just for this one function 😱
While that will not be the end of the world to anyone, it’s simply not necessary in our case, not when browsers already have structuredClone
built in.
structuredClone
not cloneThey will a throw a DataCloneError
exception:
Also throws a DataCloneError
exception:
As well as similar metadata-like features are not cloned.
For instance, with a getter, the resulting value is cloned, but not the getter function itself (or any other property metadata):
The prototype chain is not walked or duplicated. So if you clone an instance of MyClass
, the cloned object will no longer be known to be an instance of this class (but all valid properties of this class will be cloned)
More simply put, anything not in the below list cannot be cloned:
Array
, ArrayBuffer
, Boolean
, DataView
, Date
, Error
types (those specifically listed below), Map
, Object
but only plain objects (e.g. from object literals), Primitive types, except symbol
(aka number
, string
, null
, undefined
, boolean
, BigInt
), RegExp
, Set
, TypedArray
Error
, EvalError
, RangeError
, ReferenceError
, SyntaxError
, TypeError
, URIError
AudioData
, Blob
, CryptoKey
, DOMException
, DOMMatrix
, DOMMatrixReadOnly
, DOMPoint
, DomQuad
, DomRect
, File
, FileList
, FileSystemDirectoryHandle
, FileSystemFileHandle
, FileSystemHandle
, ImageBitmap
, ImageData
, RTCCertificate
, VideoFrame
And here is the best part - structuredClone
is supported in all major browsers, and even Node.js and Deno.
Just note the caveat with Web Workers having more limited support:
Source: MDN
It’s been a long time coming, but we finally now have structuredClone
to make deep cloning objects in JavaScript a breeze. Thank you, Surma.
Hi! I'm Steve, CEO of Builder.io.
We make a way to drag + drop with your components to create pages and other CMS content on your site or app, visually.
You can read more about how this can improve your workflow here.
You may find it interesting or useful:
Builder.io is a Visual CMS that let's you drag and drop to create content on your site visually, using your components.
Stop drowning in a backlog of requests - build with your whole team instead.