js 数组对象深拷贝

结论:对象的拷贝不能采用直接赋值的方式。

背景

踩过的坑如下:

formData本来是父组件传过来的,但是我不想直接用,于是我直接赋值给一个formDataCopy的对象。

但是诡异的事情发生了,就是在我填写自己的表单组件的时候,一旦表单的数据发生的变化时,本来是formDataCopy的值发生变化,但是‘formDataDefault值’ 这个字符串却被打印出来,也就是说formData改变了。

奇怪,formData是父组件传过来的值怎么会改变呢?

经过一番挣扎,才发现formDataCopy使用的是简单的赋值,导致formDataCopy和formData指向相同的对象。

formDataCopy一改变,formData就会跟着变。

以上是背景,所以我就对浅拷贝和深拷贝进行了总结:

浅拷贝

什么是浅拷贝:两者是指向一个对象。

对象的浅拷贝

1、对象的直接遍历赋值。

2、ES6中的 var copyObj = Object.assign({}, obj);

3、ES7扩展运算符 var copyObj = { ...obj }

4、Jquery浅拷贝 var copiedObject = jQuery.extend({}, originalObject) 如果改变了originalObject,copiedObject 也会变。

数组的浅拷贝

(两者指向不同的对象,但是只能拷贝一层)

  • array.concat();
  • array.slice(0);

如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变,所以是浅拷贝。

对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

也就是说,如果原数组改变的是基本数据类型,比如String,Boolean,Number的数据,不会影响到新数组; 但是如果改变的是对象或者数组中的数据,是会影响到新数组的,也也就是对于对象或者数组,新旧数组指向的是一个对象。

深拷贝

(下面说的深拷贝是基本对象的深拷贝,不考虑对象的复杂属性,比如set,get,Function等)

1、最简单的方式 JSON.parse(JSON.stringify(Obj)) 这种方法使用较为简单,可以满足基本的深拷贝需求,而且能够处理JSON格式能表示的所有数据类型,但是对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。

2、jQuery深拷贝 var copiedObject = $.extend(true, {}, originalObject)

3、手动写递归方式

var array = [
   { number: 1 },
   { number: 2 },
   { number: 3 }
];
function copy (obj) {
        var newobj = obj.constructor === Array ? [] : {};
        if(typeof obj !== 'object'){
            return;
        }
        for(var i in obj){
           newobj[i] = typeof obj[i] === 'object' ? copy(obj[i]) : obj[i];
        }
        return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); //  [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]

参考文档

https://www.cnblogs.com/penghuwan/p/7359026.html

https://github.com/wengjq/Blog/issues/3

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端面试知识点

    允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数...

    Daotin
  • 从零开始学 Web 之 JavaScript(四)数组

    arguements 是伪数组:不能修改长短的数组。(可以修改元素,但是不能变长变短)

    Daotin
  • 从零开始学 Web 之 JavaScript(五)面向对象

    (创建对象的最简单方式就是创建一个 Object 的实例,然后再为它添加属性和方法。)

    Daotin
  • JSP/Servlet Web 学习笔记 DayThree

      使用JSP语法可以存取这些内置对象来执行JSP网页的Servlet环境相互作用。内置对象其实是由特定的Java类所产生的。每一种内置对象都映射到一个特定的J...

    Rekent
  • 币聪科技:美国边境官员使用区块链认证进口证书

    美国海关与边境保护局(CBP)计划利用区块链技术核实北美自由贸易协定(NAFTA)和中美洲自由贸易协定(CAFTA)证书

    币聪财经
  • www6662016com请拨18687679362_环球国际常见Java面试题解析

    金三银四马上要来了,整理了Java一些经典面试题,也给出了答案,希望对大家有帮助,有哪里你觉得不正确的话,欢迎指出,非常感谢。

    用户7106032
  • 玩转基因组浏览器之查看gwas结果

    对列的顺序没有要求,IGV通过文件名后缀来识别文件格式,gwas结果对应的后缀可以是以下几种

    生信修炼手册
  • centos7安装telnet服务

    先检查CentOS7.0是否已经安装以下两个安装包:telnet-server、xinetd。命令如下:

    我是李超人
  • 经典面试题-final,finally,finalize的区别

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    cwl_java
  • 腾讯云黑石物理服务器标准型BMS4配置性能使用场景及注意事项

    腾讯云黑石物理服务器独享、无虚拟化的裸金属服务器,让您更灵活地构建服务,InstanceTypes分享腾讯云黑石物理服务器标准型BMS4实例配置性能包括CPU、...

    用户2416682

扫码关注云+社区

领取腾讯云代金券