美文网首页
JS 中关于浅拷贝和深拷贝的理解

JS 中关于浅拷贝和深拷贝的理解

作者: 前端_Fn | 来源:发表于2020-05-31 20:32 被阅读0次

    如何区分深拷贝和浅拷贝?

    假设 B 复制了 A ,当 A 修改时,看 B 是否跟着发生改变

    • 如果 B 改变了,说明是浅拷贝。
    • 如果 B 没改变,说明时深拷贝。

    首先,简单阐述栈堆,基本数据类型与引用数据类型。
    因为这些概念能更好的让我们理解浅拷贝和深拷贝。

    我们来举例浅拷贝的例子:

    let obj = {
        name: "张三",
        habby: {
            one: "旅行",
            two: "摸鱼"
        }
    };
    let newObj = {
        ...obj
    };
    newObj.habby.one = "打代码";  // 修改
    console.log(obj); // 打印如下 
    
    微信截图_20200531000200.png

    我明明 newObj 复制了 obj,为什么修改了 newObj ,obj 也跟着改变。那么这里,就得引入基本数据类型与引用数据类型的概念了。

    基本数据类型有哪些?

    number、string、undefined、null、symbol、boolean。


    引用数据类型

    array、object、function


    基本数据类型:名值存储在栈内存中。

    微信截图_20200531000200.png

    比如 let a = 1,当 b = a 复制时,栈内存会新开辟一个内存,例如这样:

    2.png

    所以当你修改 a = 2,对 b 并不会造成影响。当然,let a = 1,b = a。虽然 b 不受影响,但这也不算是深拷贝,因为深拷贝本身只针对较为复杂的 object 类型数据。


    引用数据类型:名存在栈内存中,值存在于堆内存中。但是栈内存会提供一个引用的地址指向堆内存中的值。

    3.png

    当 b = a 进行拷贝时,其实复制的是 a 的引用地址,并非堆里面的值。

    4.png

    而当我们a[0] = 1 时进行数组修改时,由于 a 与 b 指向的是同一个地址,所以自然 b 受了影响,所以这就是所谓的浅拷贝。

    6.png

    那,要是在推内存也开辟一个新的内存专门为 b 存放值,就是基本数据类型那样,岂不是达到深拷贝的效果。

    7.png

    方法一:通过递归去复制所有的层级属性实现深拷贝效果

    function deepCopy(obj){
        let newObj = Array.isArray(obj) ? [] : {};
        for(let key in obj){
            if(obj.hasOwnProperty(key)){
                if(typeof obj[key] === "object"){
                    newObj[key] = deepCopy(obj[key]);
                } else {
                    newObj[key] = obj[key];
                }
            }
        };
        return newObj;
    };
    let obj = {
        name: "张三",
        habby: {
            one: "旅行",
            two: "摸鱼"
        }
    };
    let newObj = deepCopy(obj);
    newObj.habby.one = '排球';
    console.log(obj)
    
    8.png

    可以看到现在 obj 脱离了 newObj 的控制,不再受 newObj 的影响了。

    方法二:通过 JSON 对象的 parse 和 stringify,缺点是对 function 和 undefined 无效。

    let obj = {
        name: "张三",
        habby: {
            one: "旅行",
            two: "摸鱼"
        }
    };
    let newObj = JSON.parse(JSON.stringify(obj));
    newObj.habby.one = '排球';
    console.log(obj);
    
    9.png

    可以看到 obj 不受 newObj 的控制了。

    可以使用 localStorage实现对象数组存储,不过这里不多说,不太推荐。

    最后,深拷贝能帮你更安全安心的去操作数据,根据实际情况来使用深拷贝。

    相关文章

      网友评论

          本文标题:JS 中关于浅拷贝和深拷贝的理解

          本文链接:https://www.haomeiwen.com/subject/rnkkzhtx.html