结构化克隆算法

结构化克隆算法是由HTML5规范定义的用于序列化复杂JavaScript对象的一个新算法。它比  JSON 更有能力,因为它支持包含循环图的对象的序列化 ---对象可以引用在同一个图中引用其他对象的对象。此外,在某些情况下,结构化克隆算法可能比JSON更高效。

算法本质上是将原始对象的所有字段的值复制到新对象里。如果一个字段是对象,这些字段会被递归复制,直到所有的字段和子字段都被复制进新的对象里。

优于 JSON 的地方

以下是结构化克隆算法相对 JSON 的一些关键优点:

  • 结构化克隆可以复制 RegExp 对象。
  • 结构化克隆可以复制 BlobFile 以及 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;
}
  注意: 此算法实际只实现了 RegExp, Array, Date 特殊对象。 根据你的需要,你可以实现其他特殊情况。

相关链接

文档标签和贡献者