JavaScript:对象:如何复制一个对象?浅拷贝与深拷贝
回顾一下,我们对传参的讨论,对象的传参是引用传递,我们传递的是对象数据所在的内存地址;
那么无论我们怎么去赋值,所有变量指向的都是同一块内存;

如上图所示,无论我去使用哪个变量去操作对象的属性,改变的始终是同一块内存区域的数据;
现在,我希望可以将obj1的内存数据,完整复制一份,存放到另一个内存区域obj2,使得这两块内存,保存的数据内容完全一样,但是我改变其中一块内存的数据,都不会影响到另一块内存的数据;
想一想,我们应该怎么做,才能达到这一目的?
浅拷贝
能想到的,是遍历对象的属性(基本数据类型),然后依次赋值给另一个对象的属性,因为说到复制,就是指值传递,只有基本数据类型是值传递:

如上图所示,我们遍历了obj1的属性,并赋值给了obj2,我们修改了obj2的name1属性,但是并没有改变obj1的name1属性,证明我们成功复制了一份obj1的内存数据;
那我们每次都需要用for-in循环吗?JS有没有自带一些方法来实现浅拷贝呢?
有的:
Object.assign()方法
语法为
Object.assign(dest, src1, src2,,,,,)第一个变量
dest是目标对象,即将后面的对象的属性值复制给目标对象;后面的所有变量
src即是源对象,会将所有源对象的属性值全复制给目标对象,如果有属性名同名,则会进行覆盖;调用该方法,结果会返回dest;

深拷贝
现在假设,obj1中,name1是一个对象类型,上面的拷贝方式,还行得通吗?

看上图,obj2对name1的name属性修改为了Bob,而obj1的name1的name属性,输出结果也为Bob,这意味着,obj1和obj2的name1属性指向的是同一块内存区域;
这是因为,对象是引用传递,我们在调用Object.assign()方法时,只是将obj1的name1的内存地址,复制给了obj2的name1,此时他们之间的内存关系,如下所示:

也就是说,此时obj1和obj2并不完全互相独立,他们之间还共同管理着name1这块内存;
这种不完全互相独立的拷贝,我们称之为浅拷贝;
所以,完全互相独立的拷贝,我们就称之为深拷贝;
那么,我们怎样才能实现深拷贝,使两者完全互相独立呢?
可行的方法是,对name1这个对象,再进行一次浅拷贝。
这样太麻烦了,JS有没有自带的深拷贝的方法呢?
JavaScript:对象:如何复制一个对象?浅拷贝与深拷贝的更多相关文章
- Python中的赋值(复制)、浅拷贝、深拷贝之间的区别
1.赋值: 只是复制了新对象的引用,不会开辟新的内存空间. 2.浅拷贝: 创建新对象,其内容是原对象的引用. 浅拷贝有三种形式:切片操作,工厂函数,copy模块中的copy函数. 如: ...
- java List复制:浅拷贝与深拷贝
Java的拷贝可以分为三种:浅拷贝(Shallow Copy).深拷贝(Deep Copy).延迟拷贝(Lazy Copy). 在java中除了基本数据类型之外(int,long,short等),还存 ...
- JavaScript对象深复制
1.原理 使用JSON,当然需要JSON安全的格式,JSON安全请参考:http://www.cnblogs.com/mengfangui/p/8257269.html 2.示例 <!DOCTY ...
- List的复制 (浅拷贝与深拷贝)
开门见山的说,List的复制其实是很常见的,List其本质就是数组,而其存储的形式是地址 如图所示,将List A列表复制时,其实相当于A的内容复制给了B,java中相同内容的数组指向同一地址,即进行 ...
- Java小知识----List复制:浅拷贝与深拷贝
原文地址: https://blog.csdn.net/demonliuhui/article/details/54572908 List浅拷贝 众所周知,list本质上是数组,而数组的是以地址的形式 ...
- Python的复制,浅拷贝和深拷贝
https://www.cnblogs.com/xueli/p/4952063.html 如果给一个变量赋值一个对象,那么新变量和原对象变量将会是同一个引用,其中一方改变,另一方也会改变. 该问题可以 ...
- JavaScript对象浅复制
1.概述 Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target). 注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面 ...
- javascript 对象的复制
1. jQuery has a method that can be used to deep-clone objects, the$.extend() function. Let’s take a ...
- JavaScript对象复制(一)(转载)
在JavaScript很多人复制一个对象的时候都是直接用"=",因为大家都觉得脚本语言是没有指针.引用.地址之类的,所以直接用"="就可以把一个对象复制给另外一 ...
- Java对象的复制
Java中对象的赋值分为浅拷贝和深拷贝 1.对象浅拷贝 public class CloneTest{ static class Emp{ String name; int age; Date h ...
随机推荐
- 如何生成均匀随机数 C++
#include <iostream> #include <fstream> #include <cstdlib> #include <ctime> u ...
- C++面向对象编程之虚指针、虚表
1.当编译器看到一个函数调用,有2个考量:静态绑定or动态绑定 静态绑定是"call xxx",xxx 是表示地址,call 是汇编语言的一个动作,它一定会调用到某个地址: 当符合 ...
- springmvc 上传文件时的错误
使用springmvc上传文件一直失败,文件参数一直为null, 原来是配置文件没写成功. <bean id="multipartResolver" class=" ...
- SSM(Spring,SpringMVC,Mybatis)框架整合项目
快速上手SSM(Spring,SpringMVC,Mybatis)框架整合项目 环境要求: IDEA MySQL 8.0.25 Tomcat 9 Maven 3.6 数据库环境: 创建一个存放书籍数据 ...
- Linux 下搭建 HBase 环境
Linux 下搭建 HBase 环境 作者:Grey 原文地址: 博客园:Linux 下搭建 HBase 环境 CSDN:Linux 下搭建 HBase 环境 前置工作 首先,需要先完成 Linux ...
- Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog
前两天看到一群里在讨论 Tomcat 参数调优,看到不止一个人说通过 accept-count 来配置线程池大小,我笑了笑,看来其实很多人并不太了解我们用的最多的 WebServer Tomcat,这 ...
- uoj349【WC2018】即时战略
题目链接 WC出了点意外滚粗了,来补补题. \(O(n^2)\)的时间复杂度,\(O(nlogn)\)的询问次数应该还是比较好想的,每次要打通到x的路径,对当前已知的树不断的找重心并询问在重心的哪颗子 ...
- C# 7.0 添加和增强的功能【基础篇】
C# 7.0 版是与 Visual Studio 2017 一起发布. 虽然该版本继承和发展了C# 6.0,但不包含编译器即服务. 一.out 变量 以前我们使用out变量必须在使用前进行声明,C# ...
- SpringBoot 常用注解的原理和使用
@AutoConfiguration 读取所有jar包下的 /META-INF/spring.factories 并追加到一个 LinkedMultiValueMap 中.每一个url中记录的文件路径 ...
- 部署redis集群
1.redis部署 redis单实例部署参考:https://www.cnblogs.com/silgen/p/16537299.html 版本:6.2.7 集群:6个节点(redis集群至少3个节点 ...