结构化克隆算法是由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;
}