对象的深克隆和浅克隆

本文参考了https://blog.csdn.net/document_dom/article/details/88537629
先看两个例子
1.1 比较两个一样的对象

       // 例子1
        var obj1={
            a:1,
            b:2,
            c:3
        }
        var obj2={
            a:1,
            b:2,
            c:3
        }
        console.log(obj1==obj2);  //false
        console.log(obj1===obj2);  //false

结果都是false

1.2 比较两个空对象

 console.log({}=={});//false
 console.log({}==={});//false

结果都是false

再看两个例子
2.1 改变obj3里面a的值 obj4的a值也会会改变

     var obj3={
            a:10
        };
        var obj4=obj3;
        obj3.a++;
        console.log(obj4);

2.2改变obj4里面a的值 obj3的a值也会会改变

  var obj3={
            a:10
        };
        var obj4=obj3;
        obj4.a++;
        console.log(obj3);

由此可以得出:相互制约 相互制衡 无法实现克隆的

看了上面的例子 我们来谈谈浅克隆到底是啥:

浅克隆定义:克隆对象的“表层”,如果对象的某些属性值又是引用类型值,则不进一步克隆他们,只是传递他们的引用

方式一 实现浅克隆方法 for in 循环实现

  var obj1={
            a:1,
            b:2,
            c:[44,55,66]
        };
        
  //实现浅克隆
        var obj2={ };
        for(var k in obj1){
            //每遍历一个k属性,就给obj2也添加一个同名的k属性
            //值和obj1的k属性值相同
            obj2[k]=obj1[k];
        }
        console.log(obj2)//输出结果说明浅克隆成功
        obj1.a++;
        console.log(obj2);
        obj1.c.push(77);
        console.log(obj2);
        console.log(obj1===obj2);true 证明了数组是同一个对象

你会发现改变obj1.a的值 obj2的a的并没有改变
改变obj1.c的值 obj2的c的改变了
说明了引用类型值并没有发生克隆
那么本质上obj1和obj2的c属性是内存中的同一个数组,并没有被克隆分开
但是整个对象浅克隆是成功了的

方式二 对象的合并 Object.assign(),第一个参数必须是个空对象

 var obj1 = {a: 1, b: 2,c:[44,55,66]};
        var obj2 = Object.assign({}, obj1);
        obj1.a++;
        console.log(obj2)
        obj1.c.push(22);
        console.log(obj2);

方式三 对象的解构赋值

 var obj1 = {a: 1, b: 2,c:[44,55,66]};
       var obj2 = {...obj1};
       obj1.a++;
       console.log(obj2)
       obj1.c.push(22);
       console.log(obj2);

深克隆定义:克隆对象的全貌,不轮对象的属性值,还是引用类型,都能将他们克隆。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var obj1={
            a:1,
            b:2,
            c:[33,44,{
                m:55,
                n:66,
                p:[77,88]
            }]
        };

        //递归函数
        function deepClone(o){
            //要判断o是对象还是数组
            if(Array.isArray(o)){
                var result=[];
                for(var i=0;i<o.length;i++){
                    result.push(deepClone(o[i]))
                }
            }else if(typeof o=='object'){
                var result={};
                for(var k in o){
                    result[k]=deepClone(o[k])
                }
            }else{
                //基本类型
                var result=o;
            }
            return result;
        }

        var obj2=deepClone(obj1);
        console.log(obj2);

        //说明两个对象中的c 已经被严格分离了
        console.log(obj1.c==obj2.c); //false

        obj1.c.push(99);
        console.log(obj2);

        obj1.c[2].p.push(120);
        console.log(obj1);
        console.log(obj2);
    </script>
</body>
</html>

通过改变obj1的引用类型 发现并没有影响到obj2的值
同时console.log(obj1.c==obj2.c); 等于false
则可验证 深克隆成功

方式二

//通过js的内置对象JSON来进行数组对象的深拷贝
function deepClone(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}

方式三

//第一个参数不传(false是不能够显示的写出来的)默认为false,是浅拷贝。传true为深拷贝。
$.extend(true,object1, object2)

//newObject 即为深拷贝出来的对象
var newObject = $.extend(true , {} , object);

注:数组的拷贝方式 参考数组的拷贝方式


版权声明:本文为qq_45716607原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。