前言

在前端开发的工作中经常需要对数据进行处理,这时候会经常使用到浅拷贝和深拷贝先拷贝原有数据再进行处理,以下就是常用的方法总结,我将以代码的形式来带大家去使用和理解这些方式

一、浅拷贝常用方法

1. Object.assign

  该方法是es6新出的一个方法,可以直接拷贝对象进行数据的处理,在vue里使用比较普遍

  使用示例:

 let obj = {name: '李信',age: 40,children: {name: '李明',age: 18}}let newObj = Object.assign({},obj)obj.name = '兰陵王'console.log(obj); // obj.name = '兰陵王'console.log(newObj); // newObj.name = '李信'

  细节: 此时浅拷贝的是对象的一级属性,所以当原始obj.name改变了以后newObj.name不会受到影响,但是对于二级属性如果还有对象就还是相同的引用地址,如下所示

  let obj = {name: '李信',age: 40,children: {name: '李明',age: 18}}let newObj = Object.assign({},obj)obj.children.name = '马超',console.log(obj); //obj.children.name = '马超'console.log(newObj); // newObj.children.name = '马超'

细节: 改变obj的chidren对象里面的值以后拷贝的newObj的值也发生了改变,说明这个方法实现的只是一级属性的浅拷贝,对于多级属性无法进行更深的拷贝

  这个方法还有个常用的用法是可以实现对象的拷贝合并

 let obj = {name: '李信',age: 40,children: {name: '李明',age: 18}}let obj2 = {name: '海王',age: 22}let obj3 = {gender: 1}let testObj = Object.assign({}, obj,obj3)let newObj = Object.assign({},obj, obj2)console.log(testObj);  console.log(newObj);

  结果如下图所示,合并对象大概分两种情况,正常合并是直接将两个对象属性名都合并拷贝到新对象,但是如果后面的对象有前面对象相同属性名,那么就会出现覆盖情况,这是需要值得去强调的

2. 数组的slice和concat方法

 这两个方法是数组的api,一个是截取数组的值,另一个可以用来连接数组,实际上还可以用来进行数组的浅拷贝复制

   使用示例:

 let arr = ['刘备','关羽','张飞','赵云','马超']let newArr = arr.slice()let newarr = arr.concat()arr[0] = '曹操'console.log(arr); // arr[0] = '曹操'console.log(newArr); // newArr[0] = '刘备'console.log(newarr); // newarr[0] = '刘备'

 细节: 从上面可以看出这两个api也是实现了数组的拷贝,改变原来的数组arr[0],拷贝后的新数组却没有受到影响,完美的实现了复制,但是这个方法也只是实现一级属性的拷贝,也就是浅拷贝

 我们工作中拿到的数据格式一般是数组对象,对于数组对象这种格式这两个方法就只能实现一级属性的拷贝,如下所示

      let arr = [{id: 111,name: '赵云',age: 18},{id: 222,name: '曹操',age:26},{id: 333,name: '刘备',age: 25}]let newArr = arr.slice()let newarr = arr.concat()arr[0].name = '孙权'console.log(arr);  // arr[0].name = '孙权'console.log(newArr);// newArr[0].name = '孙权'console.log(newarr);// newArr[0].name = '孙权'

 细节: 从上面就可以看出如果数组里面是对象这种数据,用这两个方法实现的就只是无法进行多级的拷贝,所以这两个api只能实现简单数组的浅拷贝

3. Array.from

  这个方法也是es6的一个新方法,也是常用作浅拷贝数组的一个常用方法

  使用示例:

        let arr = [{id: 111,name: '赵云',age: 18},{id: 222,name: '曹操',age:26},{id: 333,name: '刘备',age: 25}]let newArr = Array.from(arr)arr[0] = {id: 666,name: '海风',age: 66}console.log(arr);console.log(newArr);

细节从以上结果可以看出,该方法也是实现了数组的一级属性拷贝,改变原始数组的一级属性不会影响到拷贝后的新数组,但是如果改变数组对象里面的值同上面一样也是无法多级拷贝,

 在这里我就不去重复的演示了

4. es6展开运算符...

  这个应该算是浅拷贝最简单的方式,而且还很强大,数组和对象都可以用它来进行浅拷贝,话不多说,直接上代码

let obj = {name: '张三',age: 26}
let newObj = {...obj}
obj.name = '李四'
console.log(obj)  // obj.name="李四"
console.log(newObj)// newObj.name ="张三"

细节: 上面就是使用展开运算符对对象进行的浅拷贝,实现的一级属性拷贝,原始数组改变以后并不会影响到新数组

let arr = [{id: 111,name: '赵云',age: 18},{id: 222,name: '曹操',age:26},{id: 333,name: '刘备',age: 25}]let newarr = [...arr]arr[0] = {id: 666,name: '海风',age: 66}console.log(arr);console.log(newarr);

细节: 可以看出来数组浅拷贝实现的结果同上面几种也是相同的,但是展开运算符实现的也仅仅只是浅拷贝,并没有实现深层次属性的拷贝,如下图就可以看出来

    let arr = [{id: 111,name: '赵云',age: 18},{id: 222,name: '曹操',age:26},{id: 333,name: '刘备',age: 25}]let newarr = [...arr]arr[0].name = "孙权"console.log(arr); // arr[0].name = "孙权"console.log(newarr);// newarr[0].name = "孙权"

二、深拷贝常用方法

从上面可以看出来浅拷贝对于数组对象这种格式的数据无法进行深层次多级的拷贝,所以有些情景就需要用到深拷贝来实现数据的复制

1.Json.parse && Json.stringify

这个方法是深拷贝里面最容易的一种方法,利用json的api来对数组对象进行深拷贝,具体代码如下

 let arr = [{id: 111,name: '赵云',age: 18},{id: 222,name: '曹操',age:26},{id: 333,name: '刘备',age: 25}]let newArr = JSON.parse(JSON.stringify(arr))arr[0].name = "孙权"console.log(arr); // arr[0].name = "孙权"console.log(newArr); // arr[0].name = "赵云"

 细节: 先将数组对象转成json格式,然后再转变回数组,这样就可以实现深拷贝新数组,新的数组和原始数组彻底没有关系,不过这个方法也有一些缺陷,在这里我简单说一下这个方法大概的缺陷

  • 当被转化的对象里面含有时间对象这种格式的数据会被转化为字符串,代码如下
  let arr = [{id: 111,name: '赵云',age: 18,date: new Date(1280977330000)},{id: 222,name: '曹操',age:26,date: new Date(1280977330000)},{id: 333,name: '刘备',age: 25,date: new Date(1280977330000)}]let newArr = JSON.parse(JSON.stringify(arr))console.log(newArr)

  • 当对象里面有regexp格式的数据通过JSON拷贝的对象里面该数据变成了空对象,代码如下所示
 let arr = [{id: 111,name: '赵云',age: 18,reg: /^139$/},{id: 222,name: '曹操',age:26,reg: /^139$/},{id: 333,name: '刘备',age: 25,reg: /^139$/}]let newArr = JSON.parse(JSON.stringify(arr))console.log(newArr)

  • 如果拷贝的对象里面有function,则拷贝以后该数据会丢失
 let arr = [{id: 111,name: '赵云',age: 18,log: () => {console.log(123);}},{id: 222,name: '曹操',age:26,log: () => {console.log(123);}},{id: 333,name: '刘备',age: 25,log: () => {console.log(123);}}]let newArr = JSON.parse(JSON.stringify(arr))console.log(newArr)

2. 递归深拷贝

  function deepCopy(obj) {if(typeof obj !== 'object') returnlet newObj = obj instanceof Array ? [] : {}for(let key in obj) {// 含有该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: '曹操',age: 40,children: {name: '曹丕',age:30,},}let newobj = deepCopy(obj)obj.children.name = "曹忠"console.log(obj);console.log(newobj);

这个方法属于递归版的深拷贝实现方法,这个是简易版的实现方法,一些特殊情景和JSON一样也无法进行拷贝,我将专门用一节来讲一下终极版的深拷贝方法

深拷贝和浅拷贝开发常用方法总结相关推荐

  1. (0056)iOS开发之深拷贝与浅拷贝

    参考: http://blog.csdn.net/qq_17007915/article/details/50503043 http://www.cnblogs.com/ludashi/p/38941 ...

  2. iOS开发——深拷贝与浅拷贝详解

    深拷贝和浅拷贝这个问题在面试中常常被问到,而在实际开发中,只要稍有不慎,就会在这里出现问题.尤其对于初学者来说,我们有必要来好好研究下这个概念.我会以实际代码来演示,相关示例代码上传至 这里 . 首先 ...

  3. JavaScript 深拷贝与浅拷贝

    目录 深拷贝与浅拷贝 简单区分 js数据类型 基本数据类型 引用数据类型 两者存储上的区别 js实现深拷贝 深拷贝与浅拷贝 简单区分 深拷贝与浅拷贝的简单区分: 假设B复制了A,当修改A时,看B是否跟 ...

  4. C++深拷贝与浅拷贝

    浅拷贝就是成员数据之间的一一赋值:把值赋给一一赋给要拷贝的值.但是可能会有这样的情况:对象还包含资源,这里的资源可以值堆资源,或者一个文件..当 值拷贝的时候,两个对象就有用共同的资源,同时对资源可以 ...

  5. python怎么避免浅拷贝_详谈Python中的深拷贝和浅拷贝

    在平时工作中,经常涉及到数据的传递,在数据传递使用过程中,可能会发生数据被修改的问题.为了防止数据被修改,就需要在传递一个副本,即使副本被修改,也不会影响原数据的使用.为了生成这个副本,就产生了拷贝. ...

  6. 深入浅出的“深拷贝与浅拷贝”

    js中的浅拷贝与深拷贝,只是针对复杂数据类型(object, Array)的复制问题.浅拷贝和深拷贝都可以实现在已有对象上再生出一份的作用.但是对象的实例是存储在堆内存中然后通过一个引用值只操作对象, ...

  7. python怎么避免浅拷贝_深度解读Python深拷贝与浅拷贝问题

    Illustrations by Leon Tukker ♚ 作者:PayneLi,Python全家桶,主要讲述数据挖掘.机器学习和深度学习领域的前沿技术,同时还会推荐一些行业最新论文.技术专家的经验 ...

  8. 面试篇---1 如何区分深拷贝与浅拷贝

    如何区分深拷贝与浅拷贝? 简单来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力. 浅拷贝例子: var a=[0 ...

  9. 栈在前端中的应用,顺便再了解下深拷贝和浅拷贝!

    详解栈在前端中的应用 一.栈是什么 二.栈的应用场景 三.前端与栈:深拷贝与浅拷贝 1.JS数据类型 (1)js数据类型的分类 (2)js数据类型的定义和存储方式 (3)js数据类型的判断方式 2.深 ...

最新文章

  1. 借助 Evolution Linux 的帮助来轻松安装 Arch Linux
  2. Android 系统到底提供了哪些东西,供我们可以开发出优秀的应用程序(文末送书)
  3. VC++学习(6):菜单编程
  4. Seam - 无缝集成 JSF,第 3 部分: 用于 JSF 的 Ajax
  5. 【转】C#3.0入门系列(九)-之GroupBy操作
  6. 华为鸿蒙OS用户今年底或达2亿 将发布自研鸿蒙编程语言
  7. 3D动作绑定_全息3D叶修养成记?升级打怪玩转荣耀,HE叶修体验
  8. 排序算法总结(四)快速排序【QUICK SORT】
  9. C 字符串转换为c语言字符串,OC字符串与C语言字符串之间的相互转换
  10. windows安装fdfs_lient报错fdfs_client/sendfilemodule: fatal error C1189: #error: platfom not supported
  11. Zemax操作24--高斯光束的聚焦和传播
  12. Java—企业微信网页版登陆认证详解
  13. vue+tsx初体验
  14. 免费申请office365 A1 和 a1plus 带OneDrive 5T 网盘 office365学生版(转载)
  15. 【第2篇】基础数据类型
  16. 2020-05-13
  17. react+antd的后台管理项目模板
  18. MaxCompute实践之路(三) -- Java对接MaxCompute
  19. MySql排序并查询排名
  20. 靠着这份900多页的PDF面试整理,知乎上转疯了!

热门文章

  1. 《乔布斯传记》读后感(二)
  2. java计算机毕业设计客服管理系统源码+mysql数据库+系统+lw文档+部署
  3. 三款Zookeeper可视化工具、ZooInspector、prettyZoo、ZooKeeperAssistant
  4. c语言如何用串口发送数据类型,串口通信 之用C语言编写串口程序
  5. 用计算机名称无法访问,解决方案:局域网不能通过//计算机名访问,可以通过//ip地址访问...
  6. 基于Δ-Σ模数转换器的梳状滤波器的设计与matlab仿真
  7. 山东省第八届acm大赛 F题 (SDUT 3898)
  8. java多态基础_java基础(三)-----java的三大特性之多态
  9. OpenCV入门(十一)——图像平滑技术
  10. 笔记1:计算机的基本组成