-
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 = A
const 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 = A
const 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)