There are many ways to implement deep copy in JavaScript, each with its own advantages and disadvantages. Today we introduce an implementation of deep copy provided by native JavaScript structuredClone
.
Here are some common methods, along with their code examples and advantages and disadvantages:
Contents
1. UseJSON.parse(JSON.stringify(obj))
Code example:
function deepClone ( obj ) { return JSON . parse ( JSON . stringify (obj)); }
Advantages: Simple and easy to implement, effective for most object types.
Disadvantages: The prototype chain cannot be copied, and problems may occur for objects containing circular references. For example, the following code:
const calendarEvent = { date : new Date () } const problematicCopy = JSON . parse ( JSON . stringify (calendarEvent))
The final date obtained is not a Data object, but a string.
{ "date" : "2024-03-02T03:43:35.890Z" }
This is because JSON.stringify
it can only handle basic objects and arrays. Any other types are not handled as expected. For example, convert date to string. Set/Map just converts to {}
.
const kitchenSink = { set : new Set ([ 1 , 3 , 3 ]), map : new Map ([[ 1 , 2 ]]), regex : /foo/ , deep : { array : [ new File (someBlobData, ' file.txt' ) ] }, error : new Error ( 'Hello!' ) } const veryProblematicCopy = JSON . parse ( JSON . stringify (kitchenSink))
Finally, the following data is obtained:
{ "set" : { } , "map" : { } , "regex" : { } , "deep" : { "array" : [ { } ] } , "error" : { } , }
2. Use recursion
Code example:
function deepClone ( obj ) { if (obj === null || typeof obj !== 'object' ) { return obj; } let clone = obj. constructor (); for ( let attr in obj) { if (obj. hasOwnProperty (attr)) { clone[attr] = this . deepClone (obj[attr]); } } return clone; }
Advantages: Valid for any type of object, including circular references.
Disadvantages: May consume a lot of memory for large objects and may cause stack overflow.
3. Third-party libraries, such as lodash’s _.cloneDeep
method
Code example:
const _ = require ( 'lodash' ); function deepClone ( obj ) { return _. cloneDeep (obj); }
Advantages: Supports more types of objects and libraries, for example, supports Proxy objects.
Disadvantages: It will introduce dependencies and increase the size of the project.
Because this function will lead to the introduction of 17.4kb dependencies, it will be higher if only lodash is introduced.
4. Modern deep copy structuredClone
In modern browsers, you can use structuredClone
the method to implement deep copy, which is a more efficient and safer way of deep copying.
Here is a sample code that demonstrates how to use structuredClone
to make a deep copy:
const kitchenSink = { set : new Set ([ 1 , 3 , 3 ]), map : new Map ([[ 1 , 2 ]]), regex : /foo/ , deep : { array : [ new File (someBlobData, ' file.txt' ) ] }, error : new Error ( 'Hello!' ) } kitchenSink.circular = kitchenSink const clonedSink = structuredClone (kitchenSink)
structuredClone
can do:
- Copy infinitely nested objects and arrays
- copy circular reference
- Copy various JavaScript types, such as ,
Date
,Set
,Map
,Error
,RegExp
,ArrayBuffer
,Blob
,File
etc.ImageData
What cannot be copied:
- function
- DOM node
- attribute description,
setter
andgetter
- object prototype chain
Full list supported:
Array
, ArrayBuffer
, Boolean
, DataView
, Date
, Error
types (the types specifically listed below), Map
, Object
, but only ordinary objects, primitive types, except symbol
(aka number
, string
, null
, undefined
, boolean
, BigInt
), RegExp
, Set
,TypedArray
Error type:
Error
, EvalError
, RangeError
, ReferenceError
, SyntaxError
, TypeError
,URIError
Web/API type:
AudioData
, Blob
, CryptoKey
, DOMException
, DOMMatrix
, DOMMatrixReadOnly
, DOMPoint
, DomQuad
, DomRect
, File
, FileList
, FileSystemDirectoryHandle
, FileSystemFileHandle
, FileSystemHandle
, ImageBitmap
, ImageData
, RTCCertificate
,VideoFrame
Thankfully it is structuredClone
supported in all major browsers, as well as Node.js and Deno.
at last
structuredClone
We can now finally deep copy objects directly using the capabilities of native JavaScript . Each method has its pros and cons, and how you use it depends on your needs and the type of audience you’re targeting.
refer to
- Deep Cloning Objects in JavaScript, the Modern Way(www.builder.io/blog/structured-clone)
- mozilla structuredClone (developer.mozilla.org/en-US/docs/Web/API/structuredClone)