深拷贝与浅拷贝及如何实现深拷贝

先记住两句话,帮助你简单理解一下深拷贝和浅拷贝的区别:

1 深拷贝拷贝后,产生数据是两条数据
2 浅拷贝拷贝后,多个变量共用一条数据

下面,我们来看个例子:

var a = [1,2,3];
    var a1 = a;
    a1[0] = 2;
    console.log(a); //  ==>Array(3) [ 2, 2, 3 ]

是不是很奇怪,明明改变的是数组a1中的值,为什么数组a中的值也跟着改变了,这就不得不让人深思了。
那么这里,就需要引入基本数据类型和引用数据类型的概念了。
基本数据类型有哪些,number,undefined,null,string,boolean五类。
引用数据类型则有无序对象{a:1},数组[1,2,3],以及函数等。
当a1=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值。此时,就是一个浅拷贝,数组a和数组a1共用同一条数据,无论改变其中哪一个数组的值,a和a1同时都会改变。

那么,如何实现对数据的深拷贝呢???
下面,同样让我们来看几个例子:

当只考虑要深拷贝的数据为对象时

var obj = {
        a: '123',
        b: 123,
        c: {
            test: 'aaa',
            b: {
                c: {},
                d: 'hhh'
            }
        }
    }

一维对象数据的深拷贝

var obj1 = {};
    for(var x in obj){
        obj1[x] = obj[x];
    }

在这里插入图片描述
由运行结果可知,此时obj1已经完全将obj中的数据拷贝了过来。那么,现在让我们来验证一下,是否是深拷贝呢?
在这里插入图片描述
由运行结果可知,当改变对象obj中a的值时,obj1中a的值并没有发生改变。此时,即完成了对对象obj的深拷贝。但此时,仅是完成了对一层对象的深拷贝。
下面,让我们来看一下对多层对象的深拷贝,如下:

var obj1 = {};
    // for(var x in obj){
    //     obj1[x] = obj[x];
    // }
    for (var x in obj) {
        if (obj[x].constructor == Object) {
            var res = {}
            for (var k in obj[x]) {
                if (obj[x][k].constructor == Object) {
                    var res1 = {}
                    for (var j in obj[x][k]) {
                        res1[j] = obj[x][k][j];
                    }
                    res[k] = res1;
                } else {
                    res[k] = obj[x][k]
                }
            }
            obj1[x] = res
        } else {
            obj1[x] = obj[x]
        }
    }

在这里插入图片描述
由运行结果可见,已实现了多层对象的深拷贝。

总结:
一层对象的对象的深拷贝
第一步:验证数据是否是对象?
第二步:
1.创建新的空对象res
2.遍历被拷贝的obj的对象,目的为了获取所有的key value
3.将key value 添加到res中
最后将res这个对象赋值给深拷贝的对象
将来res不论赋值给哪一个变量,该变量与obj之间都是深拷贝

当只考虑要深拷贝的数据为数组时:

var arr = [1, 2, 3, 4, [1, 2, 3, 4]]
    var arr1;
    if (Array.isArray(arr)) {
        var res = [];
        for (var i = 0; i < arr.length; i++) {
            if (Array.isArray(arr[i])) {
                var res1 = [];
                for (var j = 0; j < arr[i].length; j++) {
                    res1.push(arr[i][j])
                }
                res.push(res1)
            } else {
                res.push(arr[i]);
            }
        }
        arr1 = res;
    } else {
        arr1 = arr;
    }

在这里插入图片描述在这里插入图片描述在这里插入图片描述
由运行结果可见,已实现了多层数组的深拷贝。

总结:
数组中深拷贝逻辑
第一步 验证数据是否为数组
第二步
1.新建一个空数组 res
2.遍历被拷贝的数组arr 目的为了获取arr中所有的值
3.将arr中所有元素添加到res中
4.将res赋值给需要深拷贝arr的变量arr1

递归深拷贝
递归:指的是在自己函数的内部调用自己

1.找规律
2.找出口(如果没有就是死循环)
var mh = {
        a: [1, 3],
        b: {
            a: [1, 3],
            c:{
                a:2
            }
        }
    }
    function deepCopy(options) {
        var res;
        if (options instanceof Object) {
            if (Array.isArray(options)) {
                res = []
            }
            if (options.constructor === Object) {
                res = {}
            }
            for (var k in options) {
                res[k] = deepCopy(options[k])
            }
        } else {
            res = options;
        }
        return res
    }
    var copyMh = deepCopy(mh);

在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值