通过代码绘制内存图来理解深拷贝和浅拷贝
浅拷贝
//此时有一个obj1的对象
var obj1 = {
name: 'lilei',
age: 18,
sex: 'nan',
wife: {
name: 'hanmeimei',
age: 21
}
}
//现在将obj1的内容复制给obj2
var obj2 = {}
for (var key in obj1) {
obj2[key] = obj1[key]
}
console.log(obj2);
//就会发现obj2里面也会有内容,并且和obj1的内容是一样的,那么这是深拷贝还是浅拷贝?
分析下上面的代码:
- 首先有一个对象,一个obj1的变量指向了这个对象的内存空间,在这个内存空间,有基本数据类型和复杂数据类型(wife)
- wife是一个对象(复杂数据类型),所以会开辟一块新的内存空间,wife这个变量指向这个对象的内存空间
- 有一个obj2对象,一个空空如也的对象,通过遍历obj1,将获得到的值,给obj2添加属性
- 关键点在于wife的值是一个对象,循环相当于执行了obj2.wife = obj1[‘wife’],是直接将obj1的wife的这块内存地址,直接赋值给了obj2的wife
所以这是一个浅拷贝:只拷贝第一层数据通过修改第一层数据中复杂类型数据,就拷贝的是地址,而不是全新独立的内存空间,这时候修改obj2中wife的内容,obj1也会随着改变
//此时有一个obj1的对象
var obj1 = {
name: 'lilei',
age: 18,
sex: 'nan',
wife: {
name: 'hanmeimei',
age: 21
}
}
//现在将obj1的内容复制给obj2
var obj2 = {}
for (var key in obj1) {
obj2[key] = obj1[key]
}
console.log(obj2);
//就会发现obj2里面也会有内容,并且和obj1的内容是一样的,那么这是深拷贝还是浅拷贝?
var obj3 = {}
//定义一个函数
function getCloneDeep(newObj, oldObj) {
//通过对obj1的遍历,来判断每一位属性是基本数据类型还是复杂数据类型
for (const key in oldObj) {
//如果是数组类型
if (oldObj[key] instanceof Array) {
//如果是数组类型,就让当前属性的值为空数组数组
newObj[key] = [];
//再次调用自己,循环数组,从新判断数组中的内容是什么数据类型
getCloneDeep(newObj[key], oldObj[key])
} else if (oldObj[key] instanceof Object) {
//如果是对象类型,就让当前属性的值为空对象
newObj[key] = {}
//再次调用自己,将当前的对象内容作为参数进行传递
getCloneDeep(newObj[key], oldObj[key])
} else {
//如果是基本数据类型就直接能够克隆,形成新的对象
newObj[key] = oldObj[key]
}
}
return oldObj
}
console.log(getCloneDeep(obj3, obj1));
之前步骤都一样,唯一不同的是第四步。
遇到了复杂类型数据,在代码中对数据做了判断,如果是复杂数据类型,就让新的对象的这个属性为空的复杂数据类型,然后在循环遍历,反复执行,直到全部都是基本数据类型,结束循环
所以说,通过这一种就是通过递归实现的深拷贝,每一层内存地址都是全新的,当改变obj2中的复杂数据类型的内容,obj1也是不受影响的