手动实现一个深拷贝

1,903 阅读2分钟

为什么要用深拷贝?

小伙伴们都知道,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的值并没有发生改变。说明深拷贝成功啦! ###总结 在实现深拷贝的过程中,也可以复习一下递归的知识,还是挺好的!小伙伴们也去试试吧!