资讯专栏INFORMATION COLUMN

用扩展运算符进行深拷贝的注意事项

Juven / 295人阅读

摘要:用扩展运算符深拷贝数组直接粘贴代码当数组是一维数组时,扩展运算符可以进行完全深拷贝,改变拷贝后数组的值并不会影响拷贝源的值。对象同理当对象只有一层时可以用扩展运算符进行完全深拷贝。

数组和对象的拷贝方式有很多,此处只针对扩展运算符...对数组和对象的深拷贝方式进行说明。

用扩展运算符深拷贝数组:
直接粘贴代码:

    let arr = [1, 2, 3, 4, 5, 6];
    let arr1 = [...arr];
    arr1.push(7);
    console.log(arr); //[1, 2, 3, 4, 5, 6]
    console.log(arr1); //[1, 2, 3, 4, 5, 6, 7]

数组是一维数组时,扩展运算符可以进行完全深拷贝,改变拷贝后数组的值并不会影响拷贝源的值。
但是,当数组为多维时:

    let arr = [1, 2, 3, 4, 5, 6, [1, 2, 3]];
    let arr1 = [...arr];
    arr1.push(7);
    arr1[arr1.length - 2][0] = 100;
    console.log(arr); //[1, 2, 3, 4, 5, 6,[100, 2, 3]]
    console.log(arr1); //[1, 2, 3, 4, 5, 6, [100, 2, 3],7]

由上可见,我们不难发现当改变拷贝后数组中第二层数组的值时,arr1arr1.length - 2 = 100;拷贝前数组第二层数组的值也跟着改变了。

对象同理:
当对象只有一层时:

    let obj = {
        name: "Wawa",
        age: 13,
        gender: "female"
    };
    let obj1 = {...obj
    };
    obj1.height = 165;
    console.log(obj);//{name: "Wawa", age: 13, gender: "female"}
    console.log(obj1);//{name: "Wawa", age: 13, gender: "female", height: 165}

可以用扩展运算符进行完全深拷贝。

但当对象有多层时:

    let obj = {
        name: "Wawa",
        age: 13,
        gender: "female",
        hobby: {
            a: "Chinese",
            b: "Math",
            c: "English"
        }
    };
    let obj1 = {...obj
    };
    obj1.hobby.a = "PE";
    console.log(obj); //{name: "Wawa", age: 13, gender: "female",hobby:{a: "PE", b: "Math", c: "English"}}
    console.log(obj1); //{name: "Wawa", age: 13, gender: "female", ,hobby:{a: "PE", b: "Math", c: "English"},height: 165}

扩展运算符并不能打散第二层对象的值,且无法对其进行深拷贝,拷贝前和拷贝后第二层对象的引用地址仍然是同一个,一方改变,另一方也改变。

结论:用扩展运算符对数组或者对象进行拷贝时,只能扩展和深拷贝第一层的值,对于第二层极其以后的值,扩展运算符将不能对其进行打散扩展,也不能对其进行深拷贝,即拷贝后和拷贝前第二层中的对象或者数组仍然引用的是同一个地址,其中一方改变,另一方也跟着改变

另外有一个疑问,官方说用Object.assign()拷贝时是浅拷贝,可无论我怎么操作都是深拷贝的效果,望大家指出理解错误的地方,此处贴上测试的demo:

    let obj3 = {
        name: "Gucci",
        age: 13,
        gender: "female",
        hobby: {
            a: "Chinese",
            b: "Math",
            c: "English"
        }
    };
    let obj4 = Object.assign({}, obj3);
    obj4.hobby.a = "Math";
    obj3.age = 1000;
    console.log(obj3);
    console.log(obj4.age);

无论是一层还是二层,改变拷贝之后属性的值,拷贝前对象中的任何值并没有发生改变,且互不影响,这不是深拷贝吗???

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98532.html

相关文章

  • 「前端面试题系列9」浅拷贝拷贝含义、区别及实现(文末有岗位内推哦~)

    摘要:深拷贝与浅拷贝的出现,就与这两个数据类型有关。这时,就需要用浅拷贝来实现了。数据一但过多,就会有递归爆栈的风险。这个方法是在解决递归爆栈问题的基础上,加以改进解决循环引用的问题。但如果你并不想保持引用,那就改用用于解决递归爆栈即可。 前言 这是前端面试题系列的第 9 篇,你可能错过了前面的篇章,可以在这里找到: 数组去重(10 种浓缩版) JavaScript 中的事件机制(从原生到...

    caige 评论0 收藏0
  • ​搞不懂JS中赋值·浅拷贝·拷贝请看这里

    showImg(https://segmentfault.com/img/bVbvpCA); 前言 为什么写拷贝这篇文章?同事有一天提到了拷贝,他说赋值就是一种浅拷贝方式,另一个同事说赋值和浅拷贝并不相同。我也有些疑惑,于是我去MDN搜一下拷贝相关内容,发现并没有关于拷贝的实质概念,没有办法只能通过实践了,同时去看一些前辈们的文章总结了这篇关于拷贝的内容,本文也属于公众号【程序员成长指北】学习路线...

    lauren_liuling 评论0 收藏0
  • 入理解JS拷贝

    摘要:深拷贝相比于浅拷贝速度较慢并且花销较大。所以在赋值完成后,在栈内存就有两个指针指向堆内存同一个数据。结果如下扩展运算符只能对一层进行深拷贝如果拷贝的层数超过了一层的话,那么就会进行浅拷贝那么我们可以看到和展开原算符对于深浅拷贝的结果是一样。 JS中数据类型 基本数据类型: undefined、null、Boolean、Number、String和Symbol(ES6) 引用数据类型:...

    JackJiang 评论0 收藏0
  • 关于JavaScript拷贝拷贝

    摘要:引用类型值引用类型值是保存在堆内存中的对象,变量保存的只是指向该内存的地址,在复制引用类型值的时候,其实只复制了指向该内存的地址。 前言 要理解 JavaScript中浅拷贝和深拷贝的区别,首先要明白JavaScript的数据类型。JavaScript有两种数据类型,基础数据类型和引用数据类型。js的基本类型:undefined,null,string,boolean,number,s...

    shenhualong 评论0 收藏0
  • JavaScript·随记 拷贝 vs. 浅拷贝

    摘要:而在这个运算符的相关用例中,往往会涉及到其他知识点,深拷贝和浅拷贝就是其中之一。即对象的浅拷贝会对主对象的值进行拷贝,而该值有可能是一个指针,指向内存中的同一个对象。,可以看到深拷贝和浅拷贝是对复制引用类型变量而言的。 在ES6的系列文章中,基本都会提到Spread——扩展运算符(...)。而在这个运算符的相关用例中,往往会涉及到其他知识点,深拷贝和浅拷贝就是其中之一。 背景知识 在讨...

    RyanQ 评论0 收藏0

发表评论

0条评论

Juven

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<