structuredClone()

Baseline 2022

Newly available

Since March 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

全局的 structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝

该方法还支持把原始值中的可转移对象转移到新对象,而不是把属性引用拷贝过去。 可转移对象与原始对象分离并附加到新对象;它们不可以在原始对象中访问被访问到。

语法

js
structuredClone(value)
structuredClone(value, { transfer })

参数

value

被克隆的对象。可以是任何结构化克隆支持的类型

transfer 可选

是一个可转移对象的数组,里面的 并没有被克隆,而是被转移到被拷贝对象上。

返回值

返回值是原始深拷贝

异常

DataCloneError DOMException

如果输入值的任一部分不可序列化,则抛出该异常。

附注

这个函数可以用来进行深拷贝 JavaScript 变量。 也支持循环引用,如下所示:

js
// Create an object with a value and a circular reference to itself.
const original = { name: "MDN" };
original.itself = original;

// Clone it
const clone = structuredClone(original);

console.assert(clone !== original); // the objects are not the same (not same identity)
console.assert(clone.name === "MDN"); // they do have the same values
console.assert(clone.itself === clone); // and the circular reference is preserved

Transferring values

使用可选参数 transfer 里的值,可以使可转移对象(仅)被传递,不被克隆。 传输导致原始对象(里的属性)无法继续使用。

备注: 一个可能有用的场景是在保存 buffer 之前先异步的校验里面的数据。为了避免 buffer 在保存之前有其他修改,你可以先克隆这个 buffer 然后校验数据。为了防止意外的错误引用,在传输数据时,任何修改 buffer 的尝试都会失败。

以下演示了如何把一个数组的属性转义到新对象。 返回结果时,原始对象里的 uInt8Array.buffer 会被清除掉。

js
var uInt8Array = new Uint8Array(1024 * 1024 * 16); // 16MB
for (var i = 0; i < uInt8Array.length; ++i) {
  uInt8Array[i] = i;
}

const transferred = structuredClone(uInt8Array, {
  transfer: [uInt8Array.buffer],
});
console.log(uInt8Array.byteLength); // 0

你可以克隆任意数量的对象,并传输对象的任意子集。 例如 以下代码会把 arrayBuffer1 作为值传输 但不是 arrayBuffer2

js
const transferred = structuredClone(
  { x: { y: { z: arrayBuffer1, w: arrayBuffer2 } } },
  { transfer: [arrayBuffer1] },
);

规范

Specification
HTML Standard
# dom-structuredclone

浏览器兼容性

BCD tables only load in the browser

参见