The structured clone algorithm is a new algorithm defined by the HTML5 specification for serializing complex JavaScript objects. It's more capable than JSON in that it supports the serialization of objects that contain cyclic graphs — objects can refer to objects that refer to other objects in the same graph. In addition, in some cases, the structured clone algorithm may be more efficient than JSON.
The algorithm, in essence, walks over all the fields of the original object, duplicating the values of each field into a new object. If a field is, itself, an object with fields, those fields are walked over recursively until every field and sub-field is duplicated into the new object.
Benefits over JSON
There are a few key benefits of the structured clone algorithm over JSON:
- Structured clones can duplicate
RegExp
objects. - Structured clones can duplicate
Blob
,File
, andFileList
objects. - Structured clones can duplicate
ImageData
objects. The dimensions of the clone'sCanvasPixelArray
will match the original and have a duplicate of the same pixel data. - Structured clones can correctly duplicate objects containing cyclic graphs of references.
Things that don't work with structured clones
Error
andFunction
objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw aDATA_CLONE_ERR
exception.- Attempting to clone DOM nodes will likewise throw a
DATA_CLONE_ERR
exception. - Certain parameters of objects are not preserved:
- The
lastIndex
field ofRegExp
objects is not preserved. - Property descriptors, setters, and getters (as well as similar metadata-like features) are not duplicated. For example, if an object is marked read-only using a property descriptor, it will be read-write in the duplicate, since that's the default condition.
- The prototype chain does not get walked and duplicated.
- The
Supported types
Object type | Notes |
---|---|
All primitive types | However not symbols |
Boolean object | |
String object | |
Date | |
RegExp | The lastIndex field is not preserved. |
Blob |
|
File |
|
FileList |
|
ArrayBuffer | |
ArrayBufferView | This basically means all typed arrays like Int32Array etc. |
ImageData |
|
Array | |
Object | This just includes plain objects (e.g. from object literals) |
Map | |
Set |
Another way: deep copy
If you want a deep copy of an object (that is, a recursive copy of all nested properties, walking the prototype chain), you must use another approach. The following is a possible example.
function clone(objectToBeCloned) { // Basis. if (!(objectToBeCloned instanceof Object)) { return objectToBeCloned; } var objectClone; // Filter out special objects. var Constructor = objectToBeCloned.constructor; switch (Constructor) { // Implement other special objects here. case RegExp: objectClone = new Constructor(objectToBeCloned); break; case Date: objectClone = new Constructor(objectToBeCloned.getTime()); break; default: objectClone = new Constructor(); } // Clone each property. for (var prop in objectToBeCloned) { objectClone[prop] = clone(objectToBeCloned[prop]); } return objectClone; }
RegExp
, Array
, and Date
special objects. You can implement other special cases depending on your needs.