一、前言
- 提到 JS 的深拷贝,你的脑海里可能会自动的浮现两个实现方式:
- JSON.parse(JSON.stringify(obj))
- lodash 的 cloneDeep
- 上述两种深拷贝的方式都有一些缺点,因此在学习上述深拷贝方式的时候,你可能就想过,浏览器为啥不支持原生的深拷贝呢?这不 structuredClone 就来啦~浏览器运行时原生支持的深拷贝 API
二、JSON.parse(JSON.stringify(obj)) 的缺点
1、如果你的 obj 对象存在循环引用,那么该方法会报错
const obj = {a:1};
obj.b = obj;
const obj1 = JSON.parse(JSON.stringify(obj));
2、如果你的 obj 对象存在 Date 对象,该方法会将其转化成字符串
const obj = {date: new Date()}
const obj1 = JSON.parse(JSON.stringify(obj));
obj1.date;
typeof obj1.date;
3、如果你的 obj 对象中存在 Set、Map、正则、Error 对象,该方法会将其转成空对象字面量 { } ,如果存在 undefined,该方法会直接忽略
const obj = {
set: new Set([1,2,3]),
map: new Map([[2,2]]),
reg: new RegExp(/123/),
error: new Error('123'),
none: undefined
}
JSON.parse(JSON.stringify(obj));
三、Lodash 可能存在的风险
1、Lodash 的 tree-shaking 可能和我们的使用心智有一些出入,如果你的项目脚手架没有处理该问题,你在引入方式也没有注意,那么会带来一些性能损耗。
四、structuredClone
1、MDN
- 全局的 structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝。
- 支持把原始值中的可转移对象转移到新对象,而不是把属性引用拷贝过去。 可转移对象与原始对象分离并附加到新对象;它们不可以在原始对象中访问被访问到。
2、 structuredClone 方法深拷贝的基础用法
// 普通深拷贝
const person = {
name: "Timmy",
gradutionDate: new Date('2017-06-17'),
readingBooks: ['Dream of the Red Chamber']
};
const copied = structuredClone(person);
copied.readingBooks === person.readingBooks
// 循环拷贝
const obj = {a:1};
obj.b = obj;
const obj1 = structuredClone(obj);
obj1.b === obj;
// 时间拷贝
const obj = {date: new Date()}
const obj1 = structuredClone(obj);
obj1;
typeof obj1.date
// 特殊值拷贝
const obj = {
set: new Set([1,2,3]),
map: new Map([[2,2]]),
reg: new RegExp(/123/),
error: new Error('123'),
none: undefined
}
const obj1 = structuredClone(obj);
obj1;
3、 structuredClone 不能做什么
- 不允许克隆
Function和DOM对象,如果对象中含有,将抛出DATA_CLONE_ERR异常 - 大部分
Error支持 - 对象的某些特定参数也不会被保留
- RegExp 对象的 lastIndex 字段不会被保留
- 属性描述符,setters 以及 getters(以及其他类似元数据的功能)同样不会被复制。例如,如果一个对象用属性描述符标记为 read-only,它将会被复制为 read-write,因为这是默认的情况下。
- 原形链上的属性也不会被追踪以及复制
五、对比三种深拷贝方法
- JSON.parse(JSON.stringify(obj)) 方法使用简单,且兼容性好,如果你要处理的是简单数据类型的深拷贝,该方法可以 hold 住;
- _.copyDeep 兼容性好,功能强大,对于 Function 类型不会报错,但是缺点是需要注意处理 tree-shaking 否则会有性能损耗;
- structuredClone 方法是浏览器原生支持的,对于 Function 类型会报错,但最主要的缺点是兼容性问题;
更多相关网站
JS 原生的深拷贝来啦——structuredClone mdn - structuredClone mdn - structuredClone-类型