深拷贝和浅拷贝区别:是否是真正的拷贝了一个对象的实体,而不是引用
对象中的属性,如果是引用类型(对象和数组),浅拷贝只会引用此属性的地址,如果修改此属性中的值,拷贝的对象也会修改
深拷贝则是真正的复制了这样一个对象,在内存中重新开辟一块内存空间存储,所以需要递归实现
浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。
浅拷贝实例
//此递归方法不包含数组对象
var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
var newobj = {};
for (var prop in src) {
//hasOwnProperty -- 判断是否是继承下来的属性
if (src.hasOwnProperty(prop)) {
newobj[prop] = src[prop];
}
}
return newobj;
}
因为浅复制只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致 obj.arr 和 shallowObj.arr 指向同一块内存地址,大概的示意图如下
导致的结果就是:
shallowObj.arr[1] = 5;console.log(obj.arr[1]); // 5
一处修改,处处修改
深拷贝实例
而深复制则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。这就不会存在上面 obj 和 shallowObj 的 arr 属性指向同一个对象的问题。
深拷贝实现方法:
1. 递归
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
2.JSON.parse(JSON.stringify(obj)) 实现深拷贝
注意:此方法会有限制
1. 时间对象将会被解析成时间字符串,而不是对象
2. 如果obj中有RegExp、Error对象,转换之后只能得到空对象
3.如果obj中某属性为undefined,转换之后将会丢失改属性
4.如果obj中有NaN、Infinity、-Infinity,转换之后将会变成null
5.只能拷贝对象的自有属性,如果obj中的某对象是构造函数生成的,转换之后会丢失改对象的constructor
个人理解:JSON.stringify(obj) 只会将对象转换成字符串,所以原对象(test)中的student是个Student对象,而拷贝之后的对象(test2)中只是个字符串
6.如果对象中存在循环引用的情况也无法正取实现深拷贝
3.jquery的$.extend()也可实现深拷贝
4.angular中angular.copy()也是深拷贝
参考:
https://blog.csdn.net/u014628388/article/details/77489400
https://www.imooc.com/article/70653