前言

所谓深复制与浅复制(深拷贝与浅拷贝),乍一听感觉听高大上,像是一个非常难理解的概念,其实我们平常项目开发都是在用的,只是你可能不知道该怎么叫它的名字而已,就像你听熟了一首歌,就是不知道这首歌叫什么名字一样。

在javascript中有两种数据类型,一种是基本类型,另一种是引用类型,今天说讨论的深复制与浅复制就是和这两种数据类型有直接的关系。

1、基本类型的复制

js种的基本类型有Number Boolean  String  undefined null这五类,在声明的时候,基本类型的数据都是存放在栈内存中,如下图:

首先声明的a变量会存储在栈内存里,然后又在栈内存里复制了一个a并且赋值给b,此时栈内存里汇总新分配一个内存给不,a和b的值都是abc;然后给b重新赋值,由于a和b都是独立存在的两个变量,所以两个值任何一个变化,都不会影响另外一个变量的值;通俗点来说,就是你有一个叫做a的word文档,原本在D盘里,你把它复制了一份仍在了桌面上,这个时候你对两个文件的编辑并不会相互影响,如上图。

 2、引用类型的复制

引用类型,即object,function的值都是存在堆内存中,栈内存中通过指针指向这个值在堆中的地址,而对于引用类型来说普通的赋值操作只是将指针的地址复制了一份给新的变量,属于浅复制,如下图:

这里将arr赋值给arr1,其实就是复制了arr的指针,所以arr1的指向地址和arr是一样的,这样不管操作arr还是arr1都会改变堆中数组的值,打印arr或者arr1都是改变后的值,这种情况只是改变了指针的指向,还用文件复制的形式来解释的话就是复制了一个文件的快捷方式,把它仍在桌面上,打开的仍然是源文件,如上图。

但是现在有一个需求,就是后台请求过来的json对象,在对其处理之前需要拷贝一份以方便其他开发人员再开发,如果我们用上面的赋值方式复制一份出来肯定是不行的,这样的话你下面对数据的处理也会改变源数据的值,那应该怎么处理呢?看下面代码

 function copy(obj) {
let Tobj = {}
for(var key in obj) {
Tobj[key] = obj[key] // 遍历复制属性
}
return Tobj
} var obj = {
name: "MrGao",
age: 24
};
var obj1 = copy(obj);
obj1.name = "MrBone"
console.log(obj.name) // "MrGao"
console.log(obj1.name) // "MrBone"

这样基于重新复制了一份数据出来,而且下面如果你对复制出来的数据进行修改,也不会影响源数据

但是,如果出现下面这种情况还是会有问题

 var obj = {
name: "MrGao",
age: 24,
skill: {
work: "javascript",
life: "singer"
}
};
function copy(obj) {
let Tobj = {}
for(var key in obj) {
Tobj[key] = obj[key]
}
return Tobj
}
var obj1 = copy(obj);
obj1.skill.work = "java"
console.log(obj.skill.work) // java
console.log(obj1.skill.work) // java

如此看来,值还是都改变了,上面两者只是obj中多了一个skill对象而已,由于遍历复制的只是obj中的属性,所以obj.skill作为一个引用类型对象,也只是复制了一个指针过去,所以当obj1中的skill发生了变化,obj中的skill也会变化,那么如何解决这个问题呢?

 var obj = {
name: "MrGao",
age: 24,
skill: {
work: "javascript",
life: "singer"
}
};
function copy(obj) {
let Tobj = {}
for(var key in obj) {
if (typeof(obj[key]) == 'object') {
Tobj[key] = copy(obj[key])
} else {
Tobj[key] = obj[key]
}
}
return Tobj
}
var obj1 = copy(obj);
obj1.skill.work = "java"
console.log(obj.skill.work) // javascript
console.log(obj1.skill.work) // java

为了方便理解,这里只考虑到传入的值为obj,如此,当遍历到key的值为'object'类型时,这递归调用本方法,来完成对内层对象的复制。

除了上面这种方法外,还有一种方法可以实现深复制

 var obj = {
name: "MrGao",
age: 24,
skill: {
work: "javascript",
life: "singer"
}
};
var obj1 = JSON.parse(JSON.stringify(obj)); // 先将obj转为字符串再复制
obj1.skill.work = "java"
console.log(obj.skill.work) // javascript
console.log(obj1.skill.work) // java

这种方法为先将obj转化为字符串,复制的时候就会重新在栈内存中复制一份,然后JSON.parse之后重新赋值给obj1,就实现了对对象的深复制。

总结

浅复制:之前理解的是浅复制指的是对引用对象指针的复制,并没有复制其本质内容;后来对浅复制的理解为对引用对象一层复制为浅复制,而对应的深复制为以上两种对对象进行深复制的方法。

深复制:深复制就是对一个对象通过递归,或类型转换的全面复制。

对于以上纯属个人理解,如有纰漏,欢迎指正!

js中的深复制与浅复制的更多相关文章

  1. js中的深复制和浅复制

    在实际情况中经常会遇到对对象复制的问题.比如在处理项目中的一笔多结构的数据存储或者调用,这个时候你就要对对象(json)进行操作,而不同的操作根据不同的需求来定义.其中最常见最普遍的是对对象的复制,重 ...

  2. Java中对象的深复制和浅复制详解

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...

  3. Java中的深复制与浅复制

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...

  4. C#中的深复制与浅复制

    C#中分为值类型和引用类型,值类型的变量直接包含其数据,而引用类型的变量则存储对象的引用. 对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响到另一个变量.如 class Progra ...

  5. Java中的clone()----深复制,浅复制

    这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他 ...

  6. js的深复制与浅复制

    什么是深复制和浅复制? 深复制和浅复制的概念只存在于对象array和数组obj上. 浅复制是:模糊复制,就是不管对方是字符串类型还是引用类型都通通复制过来.结果两个变量的内容会同时变化. 深复制是:有 ...

  7. .Net深复制、浅复制

    在.Net,大家都知道引用类型的深复制.浅复制吧. ,一般int等值类型是值类型(复制时是直接传值),一般的类(List<T>,Class)是引用类型(复制时传地址),默认是浅复制.若ob ...

  8. C++学习基础七——深复制与浅复制

    一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和char *str两个成员变量, 当深 ...

  9. iOS 集合的深复制与浅复制

    概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制 ...

随机推荐

  1. java IO 文件批量重命名

    java IO 文件批量重命名 package com.vfsd.renamefile; import java.io.File; import java.io.FileInputStream; im ...

  2. Spring cloud微服务安全实战-6-6jwt改造之日志及错误处理(2)

    第一次请求失败了 打印出了403,第二次更新成功 现在只处理了403这种情况,还有一种情况就是401,就是当前用户需要做身份认证,你没有做身份认证. 401的处理 与403类似,也是在这里配置.Ent ...

  3. js文档系统-jsdoc-docdash

    一.参考文档 模版:https://github.com/clenemt/docdash 例子:http://clenemt.github.io/docdash/index.html jsdoc:ht ...

  4. 正则表达式\s空格,\d数字,量词+*?测试

    之前的博文中: 有正则表达式的\b.i.\g,本文再测试了空格数字和量词的匹配.这篇只测试匹配,不替换或其他处理.\s空格:测试实际写空格也能识别,但是不利于看出空了几个空格,可以用\s代表空格.\d ...

  5. Python3-ibm_db模块-数据库操作之DB2

    官方文档 https://www.ibm.com/support/knowledgecenter/SSEPGG_9.5.0/kc_gen/developing-gen1.html 模块安装 Windo ...

  6. 了解 Selenium 定位方式

    ※元素定位的重要性:在于查找元素 And 执行元素 定位元素的三种方法 1.定位单个元素:在定位单个元素时,selenium-webdriver 提示了如下一些方法对元素进行定位.在这些定位方式中,优 ...

  7. 微信公众号使用vue,安卓端点击按钮404,ios访问正常问题

    情景:微信公众号使用vue开发的单页面,在安卓端点击按钮访问显示404,ios访问正常问题,能正常显示. 解决:将微信公众号菜单按钮设置的路径中把WWW去掉后,安卓.ios都能正常访问. 问题路径ww ...

  8. formSelects隐藏功能键

    隐藏后 方法: // selectId就是select的id,这是在select渲染完后执行 $("#selectId").parent().find(".xm-sele ...

  9. 【bcrypt】vue项目中bcrypt安装报错

    [报错] 报错时安装方法: npm install bcrypt [解决方法] npm install bcryptjs 用 bcryptjs 替换 bcrypt 即可.

  10. 人工智能对人类有哪些影响 选择Python入门怎样

    人工智能对人类有哪些影响?选择Python入门怎样?人工智能是科技时代进步的产物,也是目前人们非常关注的一个产业.那么,随着人工智能的发展,对人类生活的有哪些影响呢? 1.人工智能对文化产业影响 据了 ...