最近Vue项目中写到一个业务,就是需要把对话框的表单中的数据,每次点击提交之后,就存进一个el-table表格中,待多次需要的表单数据都提交进表格之后,再将这个表格提交,实现多个表单数据的同时提交,期间还可以用表格进行预览、修改等其他操作。将每个表单数据存进表格的代码大致代码如下:

    let object=this.ruleForm;

    this.tableData.push(object);

  其中,对话框中的表单使用了el-form,this.ruleForm是vue实例中的一个对象,而this.tableData是vue实例中的一个数组对象。直接将this.ruleForm赋值给一个变量object,然后每次再push进this.tableData里,这样看上去逻辑似乎也没啥毛病,但是,这样就会产生一个神奇的现象:每次填写表单中的数据的时候,表格中的每一行数据都会随着你表单的填写的改变而改变。

  这里就是出现了题目所谈到的问题,涉及到了js对象的直接赋值、浅拷贝与深拷贝。

直接赋值

  把一个对象a赋值给一个对象b相当于把一个对象b的地址指向对象a的地址,所以,他们实际上是同一个对象。由于这个项目是Vue,这次的问题就出现在了直接赋值上,Vue的响应式会让你更直观的知道他们的实质。以图1直接赋值的例子,person对象中有两个属性,一个是name,一个是对象属性ageAndSex;为什么要弄一个对象属性,这个会涉及到后面的浅拷贝和深拷贝问题,这也是他们之间的区别。由于内存地址我们很难监测到,但是我们可以通过严格相等运算符"==="来检测二者是否指向同一个地址。

图1 如果二者都是对象,严格相等运算符则会去检查它们是否指向相同的内存地址。

  以刚才的例子为例,如图2所示。刚开始的时候给personCopy的name属性赋值小刚,发现,person也发生了改变。给personCopy的对象属性ageAndSex的age属性赋值17,person也发生了改变。即:直接赋值,修改赋值后的对象b的非对象属性,也影响原对象a的非对象属性;修改赋值后的对象b的对象属性,也影响原对象a的对象属性

图2 直接赋值

浅拷贝

浅拷贝只会赋值制对象的非对象属性,不会指向同一个地址。ES6中有个浅拷贝的方法Object.assign(target, ...sources)。以之前直接赋值的对象为例,如图3所示。

图3 浅拷贝,赋值的对象与被复制的对象不会指向同一个地址

  修改赋值后的对象b的非对象属性,不会影响原对象a的非对象属性;修改赋值后的对象b的对象属性,却影响原对象a的对象属性,如图4所示。

图4 浅拷贝

  es6中还有一个扩展运算符"..."也可以实现浅拷贝,还是以之前的对象为例,可以写成这种形式:var personCopy= { ...person };如图5所示。

图5 扩展运算符实现浅拷贝(赋值"小刚"等的操作与之前的结果完全相同,就不全贴出来了)

  考虑到es6的支持程度,如果你的项目不支持es6,但是又想实现浅拷贝的话,也可以尝试js原生的concat方法。但由于concat只能操作数组,所以需要先将person封装为一个对象数组,写成这种形式:

    var person=[{name:"小明",ageAndSex:{age:16,sex:"男"}}];

    var personCopy=[].concat(person);

如图6所示,到时想得到person对象的时候var personCopyObjet=pesronCopy[0]即可。

图6 concat方法实现浅拷贝

深拷贝

  深拷贝会另外拷贝一份一个一模一样的对象,但是不同的是会从堆内存中开辟一个新的区域存放新对象,新对象跟原对象不再共享内存,修改赋值后的对象b不会改到原对象a。即深拷贝,修改赋值后的对象b的非对象属性,不会影响原对象a的非对象属性;修改赋值后的对象b的对象属性,也不会影响原对象a的对象属性。而且,二者不指向同一个对象。

  很明显,深拷贝比较符合我这次的业务需求。深拷贝,比较笨一点的办法就是将自己需要的数据自己封装起来。

      let object={

repayment:this.ruleForm.repayment,

interestType:this.ruleForm.interestType,

productDeadline:this.ruleForm.productDeadline,

circumstancesOfDetention:this.ruleForm.circumstancesOfDetention,

}

this.tableData.push(object);

  但是,这样明显会使代码很臃肿,而且,这还是在需要的数据只有4条的情况下,如果这个object需要封装十几条非对象属性的情况下,明显结构不复杂的情况下,这种代码需要改进。

  有一种非常简单的方法就是序列化成为一个JSON字符串,将对象的内容转换成字符串的形式,再用JSON.parse()反序列化将JSON字符串变成一个新的对象,这样原对象就与复制后的新对象没了必然的关系。以前文提到的personCopy和person为例,写法如下:var personCopy=JSON.parse(JSON.stringify(person));如图7所示。

  但是由于用到了JSON.stringify(),这也会导致一系列的问题,因为要严格遵守JSON序列化规则:原对象中如果含有Date对象,JSON.stringify()会将其变为字符串,之后并不会将其还原为日期对象。或是含有RegExp对象,JSON.stringify()会将其变为空对象,属性中含有NaNInfinity-Infinity,则序列化的结果会变成null,如果属性中有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失,因为不支持。

Buy me a cup of coffee :)

  所以,这个时候笨的办法也是有好处的,就是面对一些特殊的类型,或是对象属性复杂的情况下,因为自己对程序的需求比较了解,就可以按照自己的需要进行封装。不管黑猫白猫,能抓到老鼠的就是好猫。

js对象的直接赋值、浅拷贝与深拷贝相关推荐

  1. python数组赋值_对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解

    对Python中列表和数组的赋值,浅拷贝和深拷贝的实例讲解 列表赋值: >>> a = [1, 2, 3] >>> b = a >>> print ...

  2. Js进阶3-赋值、浅拷贝、深拷贝深度解析

    js 数据类型 基本数据类型:字符串(String).数字(Number).布尔(Boolean).对空(Null).未定义(Undefined).符号(Symbol). 引用数据类型:对象(Obje ...

  3. python赋值浅拷贝和深拷贝的区别_python赋值、浅拷贝、深拷贝区别

    在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出现一些问题.所以,在这里按个人的理解谈谈它们之间的区别. 一.赋值(assignment) 在<Py ...

  4. js的栈堆与浅拷贝、深拷贝的理解

    一:什么是堆栈?   我们都知道:在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除. 堆:队列优先,先进先出:由操作系统自动分配释放 ,存放函数的参数值, ...

  5. python赋值浅拷贝和深拷贝的区别_浅拷贝、深拷贝和普通赋值操作有什么区别?...

    对于不可变对象,创建副本没有多大意义,因为它们不会改变.对于可变对象^{},^{}和^{}的行为不同.让我们用例子来讨论它们. 赋值操作只是将源的引用赋值给目标,例如:>>> i = ...

  6. js之浅拷贝和深拷贝

    js数据类型主要分基本数据类型和引用数据类型.前者包括Number,String等,后者主要是Object,因此以下会针对不同的数据类型来分析,需要的朋友可以参考一下 1.js内存 js内存,或者说大 ...

  7. js实现浅拷贝和深拷贝

    一.数据类型 数据分为基本数据类型和引用数据类型 基本数据类型(String, Number, Boolean, Null, Undefined,Symbol) 引用数据类型(Object[Array ...

  8. 对象的浅拷贝和深拷贝

    对象的浅拷贝和深拷贝 简要介绍 代码实现 简要介绍 浅拷贝:python拷贝一般都是浅拷贝.拷贝时,对象包含的子对象内容不拷贝.因此,源对象和拷贝对象引用同一个对象 深拷贝:使用copy模块的deep ...

  9. 从JS对象开始,谈一谈“不可变数据”和函数式编程

    文章转载自:https://segmentfault.com/a/1190000008780076 作为前端开发者,你会感受到JS中对象(Object)这个概念的强大.我们说"JS中一切皆对 ...

最新文章

  1. mongoose 使用总结
  2. LaTeX入门第三集!LaTeX的几个应用!
  3. 计算机学院特色游戏,网络游戏七大特点浅析
  4. 复合高斯积分(节点数小于等于3的版本Python实现)
  5. 【数据分析R语言系列】R语言函数与函数式编程、作用域和apply 家族
  6. php屏幕共享功能,利用无线投屏技术同屏直播,精彩随时共享
  7. 计算机应用中的CAI,????按计算机应用的分类,CAI应属于()应用。
  8. oracle添加伪列,Oracle伪列 - jifengtang的个人空间 - OSCHINA - 中文开源技术交流社区...
  9. 查询2021高考成绩位次,云南一分一段表查询2021-云南高考位次查询(文科、理科)...
  10. Kafka的rebalance机制
  11. 决策树分类算法matlab,matlab实现的C45分类决策树算法
  12. discuz mysql配置文件_MySQL优化配置文件my.ini(discuz论坛)
  13. 什么是干接点、湿接点、源型、漏型、NPN、PNP
  14. word 宏命令 表头与图名的设置
  15. 《网页配色密码》 一本易读实用的好书
  16. 电驴服务器软性文件,电驴服务器.doc
  17. 64位驱动 hp630打印机_hp1020打印机64位驱动下载
  18. 如何获取广告服务流量变现数据,助力广告效果分析?
  19. https:/问题解析remote: Total 10021 (delta 0), reused 0 (delta 0), pack-reused 10021 Receiving objects: 1
  20. VC6/VS6定制应用程序按键与贴图错位问题的排查及解决

热门文章

  1. Linux系统木马后门查杀方法详解
  2. 使用qt写吃豆人游戏
  3. 白鹭引擎拉伸高度_答疑汇总|白鹭引擎架构师开源中国社区分享微信小游戏开发技巧...
  4. ZZULIOJ:1006 求等差数列的和
  5. 请问云计算的概念首次提出是在哪一年,谁提出的啊?
  6. “中国软件欧美出口工程”试点企业名单
  7. NIO笔记(一)基础内容
  8. 使用WebCollector爬虫框架进行微信公众号文章爬取并持久化
  9. 操作系统的发展和分类
  10. spring boot社区养老医疗服务平台 毕业设计源码041148