介绍
大家好,深拷贝在面试中常常被问到,在此总结了四种深拷贝的方法。
第一种 structuredClone
这个是官方给出的深拷贝api,可以轻松实现深拷贝,对比JSON.parse(JSON.stringify(Object))更加安全,目前适配了大部分浏览器,mdn是这样描述的: structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝。
缺点
- 原型:无法拷贝对象的原型链。
- 函数:无法拷贝函数。
- 不可克隆:并没有支持所有类型的拷贝,比如
Error、DOM节点。
第二种 JSON.parse(JSON.stringify(Object))
这个方法处理简单的数据类型尚可,对于一些复杂数据类型例如Date、undefinded有坑
- 更改数值:当有undefined类型或function类型的数据时会把key丢失掉,有NaN、Infinity和-Infinity这三种值的会序列化成null
- 循环饮用:当遇到循环引用的情况会报错
第三种 MessageChannel
MessageChannel是可以在Web Worker中使用的。我们可以利用这个特性在两个web worker中通信。也可以去实现深拷贝,
这个方法实际是我最近新学习的一个方法,希望大家在面试中可以多一种深拷贝的方式,
const cloneDeep = (obj) => {
return new Promise((resolve) => {
const { port1, port2 } = new MessageChannel()
port1.postMessage(obj)
port2.onmessage = ({ data }) => {
resolve(data)
}
})
}
缺点
- 异步:这样传输会有异步的问题
- function:传输的对象有function 会报错告诉你无法被clone
第四种 递归
这个方法简直是老生长谈没有什么好说的,具体直接上代码
/**
* @description 普通深拷贝
* @param {object|Array} obj
*/
const cloneDeep = (obj) => {
const objClone = Array.isArray(obj) ? [] : {}
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
if (obj[key] && typeof obj[key] === 'object') {
objClone[key] = cloneDeep(obj[key])
} else {
objClone[key] = obj[key]
}
}
}
return objClone
}