概念:
在js程序中出现两种拷贝 浅拷贝 和 深拷贝;
- 浅拷贝只是拷贝了栈空间的地址 不会拷贝堆空间的内存;当一个对象发生改变的时候 另一个对象也会受到影响;
- 深拷贝是要拷贝栈空间的地址和堆空间的内存; 所以说深拷贝之后 两个对象之间没有什么关系 ,不会受任何一方影响;
1,序列化和反序列化进行深拷贝:
错误的拷贝方法(直接赋值) ==============反向案例======================
let obj5 = {name : 'Eric',age : 18,sex : '男'};
let obj6 = obj5 ;
obj6.name = 'xinjie';
console.log("obj6:",obj6);
console.log("obj5 :",obj5);
// 会发现把原数组都改变了
obj6: { name: 'xinjie', age: 18, sex: '男' }
obj5 : { name: 'xinjie', age: 18, sex: '男' }
正确的使用方法======================序列化和反序列化==================
let obj5 = {name : 'Eric',age : 18,sex : '男'};
先序列化将对象转化为json字符串 这时对象就和下面的没有任何关系了
因为字符串是标量类型 所以说只存储在栈空间 和堆空间的对象没有任何关系
let json6=JSON.stringify(obj5);
// 再将JSON转化会对象
let newObj5=JSON.parse(json6);
// 进行改变姓名
newObj5.name = 'xinjie'
console.log("原来的对象",obj5,);
console.log("深拷贝过的对象:",newObj5);
console.log(Object.is(obj5 ,newObj5)) = false 事实证明两个对象并不相等
通过JSON.stringify实现深拷贝有几点要注意:
- 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
- 无法拷贝不可枚举的属性,无法拷贝对象的原型链上的属性
- 拷贝Date引用类型会变成字符串
- 拷贝RegExp引用类型会变成空对象
- 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
- 无法拷贝对象的循环应用(即obj[key] = obj)
2,自定义函数进行深浅拷贝
上面序列化这种深拷贝方式由于出现种种问题,最好还是我们进行封装一个可以深拷贝多层的函数,代码如下:
let arr = ['华佗','李时珍','张仲景',['白起','王翦'],'扁鹊','喜来乐'];
// 自定义函数进行深浅拷贝
function deepCopy(object){
let result;
if (Object.prototype.toString.call(object) == '[object Object]'){
result = {};
}else if (Object.prototype.toString.call(object) == '[object Array]'){
result = [];
}else{
return '不符合深拷贝的数据类型';
}
// 遍历空对象或者是空数组 也就是要拷贝的对象
for(let key in object){
if (typeof object[key] == 'object'){
result[key] = deepCopy(object[key]);
}else{
result[key] = object[key];
}
}
return result;
}
console.log(deepCopy(arr)); //[object Array]
结果如下:
[ '华佗', '李时珍', '张仲景', [ '白起', '王翦' ], '扁鹊', '喜来乐' ]
3,还可以通过Object.assign()方法和展开运算符进行深拷贝,但也不能面对多层嵌套这种情况;它们只能深拷贝一层;
.......