浅拷贝与深拷贝多种实现

浅拷贝

拷贝对象

使用for in循环实现

测试对象: obj(源), obj2(目标)
    let obj = {
            a:"1",
            b:"man",
            func:function(){
                console.log("测试");
            },
            ob:{
                ab:"第二层",
                sex:"women"
            },
            c:[],
            arr:[1,23,4,"str",{name:"数组里面的测试对象"}
        }

        let obj2 = {};
简单实现
	 for(let prop in obj){
          obj2[prop] = obj[prop];
     }

使用assign实现

	Object.assign(obj2,obj);

使用扩展运算符实现

	obj2 = {obj};

使用JSON对象拷贝

	let tmp = JSON.stringify(obj);
	obj2 = JSON.parse(tmp);

拷贝数组

使用slice或concat拷贝

测试用例 arr1(源), arr2(目标)
	 let arr1 = ["a",1,{name:"第二层",arrDeep:[1,23,5,7]}];
     let arr2 = [];
	 arr2 = arr1.slice();
     arr2 = arr1.concat();
	//结果返回的是新的引用 ,但是内容第二层会变为arr1的引用
	["a", 1, {name:"第二层",arrDeep:[1,23,5,7]}]

使用for遍历实现也行 跟对象的内容差不多

深拷贝

使用constructor判断

测试对象: obj(源), obj2(目标)
    let obj = {
            a:"1",
            b:"man",
            func:function(){
                console.log("测试");
            },
            ob:{
                ab:"第二层",
                sex:"women"
            },
            c:[],
            arr:[1,23,4,"str",{name:"数组里面的测试对象"}
        }

        let obj2 = {};
代码测试及结果
	 function  deepClone(origin){
            let target = origin.constructor === Array? []:{};//判断复制源为什么类型
            for(let prop in origin){
                if(origin.hasOwnProperty(prop)){//是否为原型链上的属性
                    if(typeof origin[prop] == "object"){//判断是否为基本数据类型
                        origin[prop].constructor === Array ?  target[prop] = []:target[prop] = {};
                        target[prop] = deepClone(origin[prop]);//为引用数据类型 深层拷贝 递归调用自身   
                    }else{
                        target[prop] = origin[prop];//正常复制
                    }
                }
            }
            return target;
        }
        obj2 = deepClone(obj);

在这里插入图片描述

使用Object.prototypy.toString.call()判断

代码测试及结果
	 function  deepClone(origin){
            let toStr = Object.prototype.toString;//保存函数引用
            let arrayStr = "[object Array]"; //储存调用函数判断为数组时返回的值
            let target = toStr.call(origin) ==  arrayStr? []:{};//判断复制源为什么类型
            for(let prop in origin){
                if(origin.hasOwnProperty(prop)){//是否为原型链上的属性
                    if(typeof origin[prop] == "object"){//判断是否为基本数据类型
                        toStr.call(origin[prop]) ==  arrayStr ?  target[prop] = []:target[prop] = {};
                        target[prop] = deepClone(origin[prop]);//为引用数据类型 深层拷贝 递归调用自身   
                    }else{
                        target[prop] = origin[prop];//正常复制
                    }
                }
            }
            return target;
        }
        obj2 = deepClone(obj);

在这里插入图片描述

使用Array.isArray()判断

代码测试及结果
	function  deepClone(origin){
            let target = Array.isArray(origin)? []:{};//判断复制源为什么类型
            for(let prop in origin){
                if(origin.hasOwnProperty(prop)){
                    if(typeof origin[prop] == "object"){//判断是否为基本数据类型
                        Array.isArray(origin[prop]) ?  target[prop] = []:target[prop] = {};
                        target[prop] = deepClone(origin[prop]);//为引用数据类型 深层拷贝 递归调用自身   
                    }else{
                        target[prop] = origin[prop];//正常复制
                    }
                }
            }
            return target;
        }
        obj2 = deepClone(obj);
结果

在这里插入图片描述

总结

深度拷贝分为一下几步:

  • 判断复制目标为数组还是对象
  • 循环遍历属性(注意排除原型链上的属性
  • 先用typeof判断是否为基本属性
  • 若是则直接复制
  • 若不是 则使用函数判断为数组或者为对象,分别赋值并递归调用自身
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值