深度克隆详解以及实现

深度克隆详解:

拷贝数组/对象没有生成新的数据,而是复制了一份引用

拷贝数据分为两种类型:

1、基本数据类型:拷贝后会生成一份新的数据,修改拷贝以后的数据不会影响原数据(没有深浅拷贝之说)

2、对象/数组:拷贝后不会生成新的数据,而拷贝的是引用,修改拷贝以后的数据影响原来的数据(有深浅拷贝之说)

注意:影响原数据的是浅拷贝

拷贝数据的方法:

1、直接赋值给一个变量(浅拷贝)

       let  obj={username:"kebi",age:18};

        let   obj1=obj;

       修改obj1的数据会影响obj的数据,所以是浅拷贝

2、Object.assign()(浅拷贝)

      let   obj2=Object.assign(obj);

      将源对象的属性赋值到目标对象上,此时obj2就有obj中的属性,修改obj2会影响原来的数据

3、Array.prototype.concat()(浅拷贝)

     let  arr=[1,2,3,4,{username:"kebi",age:18}];

     let  arr1=arr.concat()  // concat是连接数组,如果不传参,则表示复制原数组的数据到目标数组中

    注意:使用此方法时,数组中的基本数据类型的数据照样是生成一份新数据拷贝到新数组中,所以修改新数组的基本数据类型的数据不会影响原数组,如果修改数组中的对象,同样拷贝的是一份对象的引用到新数组中,所以修改新数组的对象会直接影响原来数组的对象数据。这跟直接赋值有一定的区别

4、Array.prototype.slice()(浅拷贝)

      let  arr2=arr.slice();  //slice是截取数组或者字符串,不传参表示默认全部

5、Json.parse(Json.Stringfy())(深拷贝)

      let arr3=JSON.parse(JSON.stringify(arr));

      //先把原数组转换为json字符串,变为基本数据类型,完全生成一份新数据,然后把新数据转换为js原数组,就利用了这一点,实现了深拷贝

拷贝的数据里不能有函数,处理不了,浅拷贝,拷贝的是引用,修改拷贝以后的数据会影响原数据,深拷贝(深度克隆),拷贝时生成新数据,修改不会影响原数据

下面是实现深度克隆的方法:

// 实现深度克隆----对象/数组
    function checkedType(target) {
        return Object.prototype.toString.call(target).slice(8,-1); //返回检测的数据类型
    }
    function clone(target) {
        //判断拷贝的数据类型
        //初始化变量result 成为最终克隆的数据
        let result,targetType=checkedType(target);
        if(targetType === 'Object'){
            result = {}
        }else if(targetType === 'Array'){
            result = []
        }else{
            return target;
        }
        //遍历目标数据
        for(let i in target){
            //获取遍历数据结构的每一项值
            let value = target[i];
            //判断目标结构里的每一项值是否存在对象/数组
            if(checkedType(value) === 'Object' || checkedType(value) === 'Array'){
                //继续遍历获取到的value值
               result[i]=clone(value);
            }else{ //获取到的value值是基本的数据类型或者是函数
                result[i]=value;
            }
        }
        return result;
    }
    let arr=[1,2,{username:'kebi',age:18}];
    let arr1=clone(arr);
    console.log(arr1);   
    arr1[2].username='gmx';
    console.log(arr,arr1);

总结:

    检测数据类型方法:typeof、调用对象原型的toString方法,利用call的特点实现获取数据类型。

  for   in   遍历对象:枚举对象时,输出的是属性名,枚举数组时,输出的是数组下标。

猜你喜欢

转载自blog.csdn.net/qq_41999617/article/details/83065573