浅浅理解一下深克隆和浅克隆

一、深克隆:基本数据类型的赋值

        进行深克隆的是八大基本数据类型(byte,short,int,long,float,double,char,boolean)

        大白话理解一下:就是指将数据拷贝后两者无关联,改变一个不会影响到另一个数值变化。

接下来我们来看看为什么会这样:首先,基础数据类型的存储是直接存储在栈内存中的。如此时有一个变量a,当进行赋值操作b=a时,在栈中会为变量开辟一个新的内存空间来存储b 所以a和b位于两个完全不同的存储空间,只是值相同而已,改变a自然b不会发生变化

深拷贝举例

        let a=1;
        let b=a;
        a=3;
        console.log(a)//3
        console.log(b)//1

二、浅克隆:引用数据类型的赋值

        进行浅克隆的一般是数组和对象

        继续大白话一下:浅克隆就是数据拷贝后,一方数据变化另一方会跟着变化。

引用数据类型只是把地址存在了栈内存中,真正的数据内容是存放在堆内存中的。而这类数据进行赋值时,复制过去的只是地址(相当于其他语言中的引用)。可以这样想:当我赋值  时,我只是给了你我家的门牌号,所以我们屋子里的东西是相同的,如果我拿走了一样物品,你的屋子里也会缺少这件物品(当然了,我们住在一所房子里)。当我们用obj给obj2赋值时,复制过去的只是obj的地址,所以obj改变后,obj2也跟着改变了。

对象浅拷贝举例

        let obj={
            name: 'zs',
            age: 18,
            from: 'china', 
        }
        let obj2=obj;
        obj.name="lisi"
        console.log(obj)//{name: 'lisi', age: 18, from: 'china'}
        console.log(obj2)//{name: 'lisi', age: 18, from: 'china'}

三、实现引用数据类型的深拷贝

        那么现在问题来了,假如我有一个数组或是对象,我就是想要复制一份并让他和原数组/对象毫无关系,应该怎样做呢?我们希望在地址复制过去的同时,在堆内存上为新数据开辟一块空间。

        不如先来想想怎么让引用数据类型变成基本数据类型。啊!原来有一个JSON方法实现对象、数组和字符串之间的转换! 我们先将obj变成字符串,再进行字符串的赋值(基本数据类型的赋值,深拷贝),最后再将复制好的字符串变回对象和数组不就成了吗!    

        在这里小小插入一下JSON的有关内容:

        JSON 通常用于与服务端交换数据。在接收服务器数据时一般是字符串。因此,一个常用的方法用来将数据转换成字符串:我们一般只使用他的第一个参数:需要被转换成字符串的数据内容value(通常为对象或数组),对剩下两个参数感兴趣的小伙伴可以自行查阅文档

JSON.stringify(value[, replacer[, space]])

        另一个常用的方法是将字符串转换成对象,同样,我们只使用他的第一个参数text传一个合法字符串

JSON.parse(text[, reviver])

        接下来我们就可以实现对象的深克隆了:还是上面的张三,只不过这次obj中的name变成李四之后,obj2没有跟着改变了。

        let obj={
            name: 'zs',
            age: 18,
            from: 'china', 
        }
        let tem=JSON.stringify(obj)
        let obj2=tem;
        obj2=JSON.parse(obj2)
        obj.name="lisi"
        console.log(obj)//{name: 'lisi', age: 18, from: 'china'}
        console.log(obj2)//{name: 'zs', age: 18, from: 'china'}

        那数组又该怎样操作呢,如果对象中不只是基本数据类型,又该怎样操作呢?通过上面的例子我们可以知道,对象中可能都是基本数据类型,他们以键值对的方式存在,而基本数据类型的复制是深拷贝。当我们想将一个引用数据类型进行深拷贝,只需要把里面所有的值都复制一遍就行了!

        接下来我们封装一个实现数据深克隆的函数deepClone

        var obj1 = {
            a: 1,
            b: {
                like: 'eat'
            },
            arr: ['ad', 11,[1,2,3]]
        }
        const deepClone = (obj) => {
            if (typeof (obj) == "object") {
                let res;
                console.log("引用数据类型")
                if (Array.isArray(obj)) {
                    res = [];
                    console.log("数组")
                    for (val of obj) {
                        res.push(deepClone( val ))
                    }
                } else {
                    res = {};
                    console.log("对象")
                    for (item in obj) {
                        res[item]= deepClone(obj[item])
                    }
                }
                return res
            } else {
                console.log("基本数据类型")
                return obj
            }
        }
        var obj2 = deepClone(obj1);
        obj1.b.like = "drank"
        obj1.a="hello"
        obj1.arr[2][1]="world"
        console.log(obj1)
        console.log(obj2)

        最后输出的结果如图,让我们来分析一下这个函数是如何执行的:我们创建一个空遍历res用来存储最后的结果。首先obj是一个对象,循环遍历对象中的三个元素,第一个是基本数据类型,将其值obj[item]也就是1递归调用函数作为参数,因为他是基本数据类型,所以直接返回了。第二个元素同样递归后因为是对象,再递归一次变成基本数据类型返回。第三元素...n次递归之后,所有元素都成功在变成基本数据类型之后被复制了。左下输出很清晰的展现了函数的执行过程。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值