方法一:解构赋值
1. 演示
obj2 = {...obj1}
2. 存在问题
只能深拷贝一层,再深层次的对象不能被深拷贝,只能被浅拷贝
方法二:JSON 转换
1. 演示
obj2 = JSON.parse(JSON.stringify(obj1))
2. 存在问题
① bigint 类型的值无法转换,会报错
② undefined、symbol、function 等类型的值,会丢失
③ error regexp 等类型的值,会变为空对象
④ date 类型的值,会变为字符串,即使再次变为对象,属性值还是字符串
参考:深拷贝循环引用的处理
方法三:自定义深拷贝函数
<script>
let p1 = {
age: 38,
son: {
name: '小贝'
},
arr: [1, 2, 3, 4],
// 以下不属于循环引用
p1: {
age: 38,
son: {
name: '小贝'
},
arr: [1, 2, 3, 4],
p1: {
age: 38,
son: {
name: '小贝'
},
arr: [1, 2, 3, 4],
}
}
}
// p1.next = p1 // 循环引用
p2 = deepClone(p1)
// console.log(p2)
function deepClone(targetObj, map = new WeakMap()) {
// 首先判断是否是基本类型,若是,直接返回
if (typeof targetObj !== 'object') { // typeof 判断,'object' 包括了 array,object,null 三种
return targetObj
}
// 判断是数组还是对象类型
let cloneObj = Array.isArray(targetObj) ? [] : {}
// 防止循环引用
if (map.get(targetObj)) throw new Error('拷贝对象存在循环引用')
map.set(targetObj, cloneObj) // key 是源对象,value 是克隆对象
// console.log(map)
for (key in targetObj) {
// 确保是自身的属性,而不是原型链上的属性
if (targetObj.hasOwnProperty(key)) {
// 递归克隆,直到返回的是基本类型
cloneObj[key] = deepClone(targetObj[key], map)
}
}
return cloneObj
}
</script>