Window: structuredClone() 方法

Baseline 已廣泛支援

此特性已經十分成熟,可在許多裝置和瀏覽器版本上使用。自 2022 年 3 月起,它已在各瀏覽器中可用。

Window 介面的 structuredClone() 方法使用結構化克隆演算法建立一個給定值的深層克隆

該方法還允許將原始值中的可轉移物件轉移而不是克隆到新物件。轉移的物件將從原始物件中分離並附加到新物件;它們在原始物件中不再可訪問。

語法

js
structuredClone(value)
structuredClone(value, options)

引數

value

要克隆的物件。這可以是任何可結構化克隆的型別

options 可選

具有以下屬性的物件:

transfer

一個可轉移物件陣列,這些物件將被移動而不是克隆到返回的物件中。

返回值

原始 value深層副本

異常

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

轉移值

(只有)可轉移物件可以使用 options 引數的 transfer 屬性進行轉移,而不是在克隆物件中複製。轉移會使原始物件無法使用。

注意: 一個可能有用的場景是在儲存資料之前非同步驗證緩衝區中的某些資料。為了避免緩衝區在資料儲存之前被修改,您可以克隆緩衝區並驗證該資料。如果您同時轉移資料,任何修改原始緩衝區的嘗試都將失敗,從而防止其被意外濫用。

以下程式碼展示瞭如何克隆陣列並將其底層資源轉移到新物件。返回時,原始的 uInt8Array.buffer 將被清除。

js
// 16MB = 1024 * 1024 * 16
const uInt8Array = Uint8Array.from({ length: 1024 * 1024 * 16 }, (v, 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] },
);

示例

克隆物件

在此示例中,我們克隆了一個帶有一個成員(陣列)的物件。克隆後,對每個物件的更改不會影響另一個物件。

js
const mushrooms1 = {
  amanita: ["muscaria", "virosa"],
};

const mushrooms2 = structuredClone(mushrooms1);

mushrooms2.amanita.push("pantherina");
mushrooms1.amanita.pop();

console.log(mushrooms2.amanita); // ["muscaria", "virosa", "pantherina"]
console.log(mushrooms1.amanita); // ["muscaria"]

轉移物件

在此示例中,我們建立一個 ArrayBuffer,然後克隆它是其成員的物件,同時轉移緩衝區。我們可以在克隆物件中使用緩衝區,但如果我們嘗試使用原始緩衝區,則會引發異常。

js
// Create an ArrayBuffer with a size in bytes
const buffer = new ArrayBuffer(16);

const object1 = {
  buffer,
};

// Clone the object containing the buffer, and transfer it
const object2 = structuredClone(object1, { transfer: [buffer] });

// Create an array from the cloned buffer
const int32View2 = new Int32Array(object2.buffer);
int32View2[0] = 42;
console.log(int32View2[0]);

// Creating an array from the original buffer throws a TypeError
const int32View1 = new Int32Array(object1.buffer);

規範

規範
HTML
# dom-structuredclone

瀏覽器相容性

另見