为什么要用深拷贝?
小伙伴们都知道,js中的对象属于引用类型,单纯的用等号赋值,其实复制的是引用地址,真正指向的还是堆内存中同一个值,当一个值的内部属性变化时,另一个值由于指向的是堆内存中的同一个值,所以也会发生变化。这往往是我们不想要的结果,我也在项目中因为这个吃过大亏,所以一起来讨论讨论吧!
如何手动实现一个深拷贝?
方法1:JSON.stringify ,JSON.parse
通过JSON.stringify
,JSON.parse
可以实现深拷贝,但是有个坑得注意下,在序列化JavaScript对象时,所有函数和原型成员会被有意忽略。看下面这个案例:
var a = {
name:"西瓜",
run:function(){
console.log(123)
}
}
console.log(JSON.parse(JSON.stringify(a)));
可以看出,在拷贝的过程中,对象中的run
方法不见了。
方法2:递归
话不多说,直接上代码:
//主入口函数
function deepCopy(obj){
if(typeof obj === "object"){
//是一个数组
if(Array.isArray(obj)){
return copyArray(obj);
}else{
//是一个对象
return copyObj(obj);
}
}
}
//如果是对象类型的,执行该函数
function copyObj(obj){
var newObj = {};
for(let key in obj){
if(typeof obj[key] === "object"){
//obj[key]还是属于object类型的话,递归执行deepCopy
newObj[key] = deepCopy(obj[key]);
}else{
newObj[key] = obj[key];
}
}
return newObj;
}
//如果是数组类型类型的,执行该函数
function copyArray(array){
var newArr = [];
array.forEach((item,index)=>{
//item还是属于object类型的话,递归执行deepCopy
if(typeof item === "object"){
newArr.push(deepCopy(item));
}else{
newArr.push(item);
}
});
return newArr;
}
//测试
var testObj = [{
name:"西瓜",
info:{
age:10,
adress:"杭州"
}
},
"哈哈哈哈哈",
{
run:function(){
console.log(123)
}
}
];
var deepObj = deepCopy(testObj);
testObj[1] = "我改变了数组里面的一个值";
console.log(testObj);
console.log(deepObj);
运行结果如下:
结果中看到,deepObj
是使用深拷贝函数后得到的结果,在这之后去修改testObj
的值,deepObj
的值并没有发生改变。说明深拷贝成功啦!
###总结
在实现深拷贝的过程中,也可以复习一下递归的知识,还是挺好的!小伙伴们也去试试吧!