结构化克隆算法是由HTML5规范定义的用于序列化复杂JavaScript对象的一个新算法。它比 JSON 更有能力,因为它支持包含循环图的对象的序列化 ---对象可以引用在同一个图中引用其他对象的对象。此外,在某些情况下,结构化克隆算法可能比JSON更高效。
算法本质上是将原始对象的所有字段的值复制到新对象里。如果一个字段是对象,这些字段会被递归复制,直到所有的字段和子字段都被复制进新的对象里。
优于 JSON 的地方
以下是结构化克隆算法相对 JSON 的一些关键优点:
- 结构化克隆可以复制
RegExp
对象。 - 结构化克隆可以复制
Blob
、File
以及FileList
对象。 - 结构化克隆可以复制
ImageData
对象。CanvasPixelArray
的克隆粒度将会跟原始对象相同,并且复制出来相同的像素数据。 - 结构化克隆可以正确的复制有循环引用的对象
结构化克隆所不能做到的
Error
以及Function
对象是不能被结构化克隆算法复制的;如果你尝试这样子去做,这会导致抛出 DATA_CLONE_ERR 的异常。- 企图去克隆 DOM 节点同样会抛出 DATA_CLONE_ERROR 异常。
- 对象的某些特定参数也不会被保留
RegExp
对象的 lastIndex 字段不会被保留- 属性描述符,setters 以及 getters(以及其他类似元数据的功能)同样不会被复制。例如,如果一个对象用属性描述符标记为 read-only,它将会被复制为 read-write,因为这是默认的情况下。
- 原形链上的属性也不会被追踪以及复制。
支持的种类
对象类型 | 注意 |
---|---|
所有的原始类型 | 除了symbols |
Boolean 对象 | |
String 对象 | |
Date | |
RegExp | lastIndex 字段不会被保留。 |
Blob |
|
File |
|
FileList |
|
ArrayBuffer | |
ArrayBufferView | 这基本上意味着所有的 类型化数组 ,比如 Int32Array 等等。 |
ImageData |
|
Array | |
Object | 仅包括普通对象 (比如对象字面量 ) |
Map | |
Set |
另一种方法:深复制
如果你想深复制一个对象(那就是沿着原形链,对所有属性进行递归复制),你必须要用另外一种方法。以下是一个可行的例子。
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; }