在日常开发中,我们经常遇到需将一个对象的值赋给一个新的对象,这个时候如果不想让新赋值的对象属性修改时影响到原对象的属性,此时我们就要使用到深拷贝,那具体怎么实现,今天我们就来分析一下
首先需要搞明白js的数据类型有哪些
一、js数据类型
1、基本数据类型:String(字符串类型)、Number(数值类型)、Boolean(布尔值)、Null、undefined
2、引用数据类型:Array、Object、Function
明白了数据类型之后让我们看一下他们在内存中的区别
二、栈内存和堆内存
1、基本数据类型在内存中存放在栈中,存放的是具体的值
可以看到,当我们声明一个变量时,会在栈中开辟一个空间,因为赋值的是基本数据类型的数据所以会将值存放在栈中,此时如果将num的值赋给num2,会直接将num在栈中存储的值直接赋给num2
2、引用数据类型在内存中的是地址
引用数据类型在声明时,会在内存中开辟两块空间,在栈中存放的是地址,这个地址指向了堆空间中存放的具体数据,此时如果将arr1直接赋值给arr2,那么实际是将arr1在栈空间中的地址赋给了arr2,arr2可以通过这个地址访问的堆内存中同样的数据。这个就是浅拷贝,如果此时arr通过下标修改了堆空间中的数据,那么arr1访问时数据也会发生改变,造成数据之间的影响。
搞清楚了基本数据类型和引用数据类型后让我们看一下深浅拷贝具体如何实现
三、深浅拷贝
首先深浅拷贝仅针对引用数据类型而言,基本数据类型因为将值直接存放在栈中,所以不存在深浅拷贝的概念
1、浅拷贝:上述的引用类型的赋值就是浅拷贝,只拷贝地址
2、深拷贝:我们用json数据模拟数据,运用递归实现深拷贝
var p = {
id: "007",
name: "刘德华",
wife: {
id: "008",
name: "刘德的妻子",
address: {
city: "北京",
area: "海淀区",
},
},
};
//写函数
function copyObj(obj) {
let newObj = {};
for (let key in obj) {
if (typeof obj[key] == "object") {
//如:key是wife,引用类型,那就递归
newObj[key] = copyObj(obj[key]);
} else {
//基本类型,直接赋值
newObj[key] = obj[key];
}
}
return newObj;
}
let pNew = copyObj(p);
console.log(pNew);
打开控制台我们发现这个数据已经拷贝好了
此时我们修改拷贝后的id值可以看到原对象的值并没有发生改变,说明他们两个的空间地址已经不一样了