js中的深拷贝和浅拷贝

JavaScript 中对象的浅拷贝和深拷贝有如下区别: 
浅拷贝:仅仅复制对象的引用,而不是对象本身。 

深拷贝:复制对象所引用的全部对象。

浅拷贝:

1.自定义实现

function simpleClone(obj) {
                var simpleCloneObj = {};
                for (var i in obj) {
                    simpleCloneObj[i] = obj[i];
                }
                return simpleCloneObj;
            }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.使用Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

var simpleClone= Object.assign({}, obj);
 
 
  • 1
  • 1

深拷贝: 
1.使用 JSON.parse() 方法

            function deepClone(obj) {
                var deepCloneObj = {};
                try {
                    deepCloneObj = JSON.parse(JSON.stringify(obj));
                }
                catch (e) {
                }
                return deepCloneObj;
            }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这种方法虽然简单,但是有如下的问题,它会抛弃对象的constructor,也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。 
这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象(自己百度一下),即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

  1. 递归拷贝 
    第二个参数可以用来实现追加。
    function deepClone(initalObj, finalObj) {
                var deepCloneObj = finalObj || {};
                for (var i in initalObj) {
                    var prop = initalObj[i];

                    // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
                    if (prop === deepCloneObj) {
                        continue;
                    }

                    if (typeof prop === 'object') {
                        deepCloneObj[i] = (prop.constructor === Array) ? [] : {};
                        arguments.callee(prop, deepCloneObj[i]);
                    } else {
                        deepCloneObj[i] = prop;
                    }
                }
                return deepCloneObj;
            }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3.使用Object.create()方法

  function deepClone(initalObj, finalObj) {
                var deepCloneObj = finalObj || {};
                for (var i in initalObj) {
                    var prop = initalObj[i];

                    // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
                    if (prop === deepCloneObj) {
                        continue;
                    }

                    if (typeof prop === 'object') {
                        deepCloneObj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
                    } else {
                        deepCloneObj[i] = prop;
                    }
                }
                return deepCloneObj;
            }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

当直接使用下面的方法也可以达到深拷贝的效果。

var deepCloneObj= Object.create(oldObj);
 
 
  • 1
  • 1

那么现在来测试一下浅拷贝的方法。

    var cloneObj = simpleClone(obj);

                console.log(cloneObj.name);
                console.log(cloneObj.val);

                cloneObj.name = "simpleCloneTest2";
                cloneObj.val = [3, 4, 5];

                console.log(cloneObj.val);
                console.log(obj.name);
                console.log(obj.val);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

执行结果如下:

simpleCloneTest
 [0, 1, 2]

 simpleCloneTest2
 [3, 4, 5]

 simpleCloneTest
 [0, 1, 2]
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

我们发现在cloneObj 更改name和val时,obj的值并没有更改。这是为什么呢?我们稍后说明。 
我们再来另一种测试。

var obj = {
                    name: "simpleCloneTest",
                    val: [0, 1, 2]
                };
                var cloneObj = simpleClone(obj);

                console.log(cloneObj.name);
                console.log(cloneObj.val);

                //cloneObj.name = "simpleCloneTest2";
                //cloneObj.val = [3, 4, 5];
                //console.log(cloneObj.name);
                //console.log(cloneObj.val);

                //console.log(obj.name);
                //console.log(obj.val);

                  cloneObj.name = "simpleCloneTest3";
                cloneObj.val[0] = 3;

                console.log(cloneObj.name);
                console.log(cloneObj.val[0]);

                console.log(obj.name);
                console.log(obj.val[0]);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

输出结果如下:

simpleCloneTest
[0, 1, 2]

simpleCloneTest3
3

simpleCloneTest
3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值