-
?structuredClone()
- ?JavaScript 中提供了一個原生 API 來執行對象的深拷貝:
structuredClone
。它可以通過結構化克隆算法創建一個給定值的深拷貝,并且還可以傳輸原始值的可轉移對象。
當對象中存在循環引用時,仍然可以通過?structuredClone()
?進行深拷貝。
const A = {set: new Set([1, 3, 3]),map: new Map([[1, 2]]),regex: /foo/,error: new Error('Hello!')}A.a = Aconst copied = structuredClone(A)console.log(copied)
注意:
原型鏈不能被遍歷或拷貝(克隆的對象將不再是這個類的一個實例(但是這個類的所有有效屬性都將被拷貝))?
不能拷貝函數、方法DOM節點?、屬性描述符、setter
?和?getter
?以及類似的元數據不能被克隆
支持拷貝的類型:?
Array(數組)、ArrayBuffer(數據緩沖區)、Boolean(布爾類型)、DataView(數據視圖)、Date(日期類型)、Error(錯誤類型,包括下面列出的具體類型)、Map(映射類型)、Object (僅指純對象,如從對象字面量中創建的對象)、原始類型(除symbol
外,即 number、string、null、undefined、boolean、BigInt)、RegExp(正則表達式)、Set(集合類型)、TypedArray(類型化數組)。
-
JSON.parse(JSON.stringify())
使用時需要注意:?
JSON.stringify
?只能處理基本對象、數組和基本類型,而其他類型的值在轉換之后都可能出現出乎意料的結果,例如 Date 會轉化為字符串, Set 會轉化為?{}
。
JSON.stringify
甚至完全忽略某些內容,比如undefined
或函數。?
JSON.parse(JSON.stringify(x))
?無法對包含循環引用的對象進行深克隆
const A = {set: new Set([1, 3, 3]),map: new Map([[1, 2]]),regex: /foo/,error: new Error('Hello!')}A.a = Aconst copied = JSON.parse(JSON.stringify(A))
報錯:
?
所以,如果對象沒有上面說的這些情況,使用?JSON.parse(JSON.stringify(x))
?進行深克隆是完全沒有問題的。如果有,就可以使用?structuredClone()
?來進行深拷貝。
實現深拷貝只需以下三個核心步驟:
- 創建出對應數據類型的空白數據。即,若須拷貝的是對象類型數據,則創建一個空白對象,以此類推。
- 拷貝目標數據。即把目標數據拷貝到步驟1中創建的空白數據里。
- 返回拷貝的數據。
export function deepClone(data: any){// 普通類型數據則直接返回// 循環引用處理// 1. 創建對應類型的空白數據// 2. 復制// 3. 返回}
其他拷貝方式:?
?Object.assign/解構賦值/arr.concat
當拷貝內容中數據的值都是簡單數據類型時,是深拷貝
當拷貝內容中數據的值出現引用數據類型時,引用數據仍然是淺拷貝,只有簡單數據類型是深拷貝
轉載于:
JavaScript 中更現代的深拷貝方法! - 掘金 (juejin.cn)