这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战
新入职就开始忙,连续两周11点下班了,但依然要继续,日积月累能养成好的习惯,也能厚积薄发
今天项目里碰到一个深拷贝浅拷贝的问题,大概场景是利用ES6的数组解构时,也会触发
let [a, b=a] = [{ type:1 }]
a.age = 1
b.age = 2
console.log(a.age) // 2
a和b同时获得一个对象,而当再次赋值时,b的值也覆盖到了a的身上,那么是在赋值对象的时候就已经浅拷贝了吗?试一试
let [a, b=a] = [12]
a=1
b=2
console.log(a) // 1
let [a, b=a] = ["12"]
a="1"
b="2"
console.log(a) // "1"
当同时赋值为数字或者字符串时,b却并没有覆盖a的值
let [a, b=a] = [[12]]
a[1] = 1
b[1] = 2
console.log(a) // [12, 2]
当同时赋值为数组时,b却把a给覆盖了
- 那么当赋值为对象或者数组时,是对引用类型数据进项等号赋值,则为浅拷贝
- 而赋值为数字或者字符串时,是对基本数据类型进行等号赋值,则为深拷贝
那么再看下深拷贝和浅拷贝的定义
-
深拷贝:修改新变量的值不会影响原有变量的值。默认情况下基本数据类型(number,string,null,undefined,boolean),深拷贝会重新创建一个相同的对象,新对象有自己的指针和内存空间
-
浅拷贝:修改新变量的值会影响原有的变量的值。默认情况下引用类型(object)都是浅拷贝,浅拷贝复制了指向某个对象的指针,并没有复制对象的值,新旧对象还是共享同一个内存空间
咦?发现没有,object,没有存在array,那么又引发了疑问,为什么,接下来,看一下深拷贝浅拷贝的实现方法
function deepClone(source){
const targetObj = source.constructor === Array ? [] : {};
for(let keys in source){
if(source.hasOwnProperty(keys)){
if(source[keys] && typeof source[keys] === 'object'){
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
}else{
targetObj[keys] = source[keys];
}
}
}
return targetObj;
}
typeof source[keys] === 'object'注意一下这里的typeof,哦原来用了这个判断,typeof中array返回的也是"object",这就想得通了
如果是object,再判断是否为数组,如果是数组赋值为空,进行递归克隆数组中的每一项,或者为对象赋值为空,递归赋值对象的所有值
值得一提的是,Object.assign也是浅拷贝
let a = { type: 1 }
let b = Object.assign(a)
b.type = 2
console.log(a.type) // 2
那么如何让浅拷贝变成深拷贝?
利用JSON.parse(JSON.stringify(需要实现深拷贝的数组或对象))
但需要注意的是:
JSON.parse(JSON.stringify(需要实现深拷贝的数组或对象))不能处理函数或者RegExp
看到这里,恍然大悟有吗,有句话叫在实战中学习,便是如此