所谓深拷贝与浅拷贝,乍一听我也蒙了,仔细一看其实就是C#中值类型复制和引用类型复制的区别。
值类型自然不存在这个概念,因为你怎么复制都是两个数据,但是引用类型就不一样了,引用类型涉及到引用的复制和值的复制问题。因此下面没有提到数据类型时候都是在说引用类型哈!
深拷贝就是引用类型复制时不仅仅将存在栈中的引用复制,同时还将堆中的数据复制了一份,从而得到了两份数据。
浅拷贝就是平常的赋值方式,仅仅将栈中的引用复制了,但是堆中的数据并没有复制。
【值类型数据放在栈中;引用类型数据在堆中,引用在栈里】
1.引用类型中常见的深拷贝方式
①数组:采用es6的...展开
let a=[1,2,3],
let b=[...a];
②json:采用es6的...展开
let a={"c":12};
let b={...a};
③系统对象
Date等,直接将其实例作为新对象创建过程中构造函数的参数即可【因为系统对象已经帮你实现了这个过程】
let a=new Date();
let b=new Date(a);
这样b就对a实现了深拷贝
④自定义对象
与系统对象方式一样,但是前提你要自己写拷贝方法。
⑤symbol类型
有关symbol内容请看:https://es6.ruanyifeng.com/#docs/symbol
symbol类型的深拷贝要利用symbol.for进行,同时利用ES2019 提供了一个实例属性description,直接返回 Symbol 的描述。
let s1=symbol.for('wayne');
let s2=symbol.for(s1.description);
这样s2就实现了对s1的深拷贝。
2.完整深拷贝通用代码
//[4]深拷贝方法
function clone(data){
//1.判断symbol类型
if (typeof data=="symbol"){
return symbol.for(data.description);
}
//2.判断值类型(即不是object类型)
else if (typeof data!="object"){
return data;
}
//3.判断数组
else if (data.constructor===Array){
return data.map(i=>clone(i));
}
//4.判断json类型
else if (data.constructor===Object){
let tem={};
for(let key in data){
tem[key]=clone(data[key]);
}
return tem;
}
//5.判断系统对象和自定义对象
else{
return new data.constructor(data);
}
}
注意,对于数组和json格式来说,单纯的...展开只能实现一层的拷贝,如果想多层拷贝,就要用到上述代码中3和4所写的那样,利用递归。
3.总结
目前针对深拷贝浅拷贝就这么多,欢迎留言指正讨论