专栏首页亦枫的大佬之路JavaScript中的拷贝(copy)

JavaScript中的拷贝(copy)

JavaScript中的拷贝分为两种: 深拷贝,浅拷贝。

为什么要使用深拷贝和浅拷贝呢?

如果现有var obj1 = {…}这个对象,想要复制对象obj1,一贯的做法就是obj2 = obj1,这时虽然obj2拥有了obj1的所有属性,但obj2却不是自由的,因为它的改动会影响到obj1,obj1的改动也会影响到obj2,这不是我们所希望的,所以要用到深拷贝和浅拷贝。

如何区分深拷贝与浅拷贝?

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

  1. 浅拷贝(shallow copy):只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存;
  2. 深拷贝(deep copy):复制并创建一个一摸一样的对象,不共享内存,修改新对象,旧对象保持不变;

深拷贝与浅拷贝的拷贝对象

首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。

js基本类型的分类以及包含哪些?

基础类型:undefined 、 null、number、string、boolean、symbol

引用类型:object对象类型(Object 、Array 、Function 、Data)

而这两类数据存储分别是这样的:

a.基本类型–名值存储在栈内存中,例如let a=1;

当你b=a复制时,栈内存会新开辟一个内存,例如这样:

所以当你此时修改a=2,对b并不会造成影响,因为此时的b已自食其力,翅膀硬了,不受a的影响了。当然,let a=1,b=a;虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。

b.引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值,我们以上面浅拷贝的例子画个图:

当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值。

而当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了。

那,要是在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,岂不就达到深拷贝的效果了。

深拷贝的实现

实现深拷贝主要有2种方法

(1)递归

(2)JSON.stringify结合JSON.parse

1.递归 这里的递归我们用jquery中的$.extend。

var tal = {name:'lili'};
	Cal=$.extend(true,{},tal);
tal.name='kiki';
console.log(tal,Cal);  //{name: "kiki"}{name: "lili"}

2.JSON.stringify结合JSON.parse

function test(obj){
    let _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
    return objClone
}
var tal = {name:'lili'};
Cal=test(tal);
Cal.name = 'kiki';
console.log(tal,Cal);  //{name: "lili"} {name: "kiki"}

注意

1.深拷贝中,副本和原对象不共享属性。

2.深拷贝递归的复制属性。

3.深拷贝的副本不会影响到原对象,反之亦然。

4.js中所有的原始数据类型默认执行深拷贝,比如Boolean, null, Undefined, Number,String等。

实际工作中,深拷贝(递归的对对象里每一层值和对象进行拷贝)应用很广泛,浅拷贝几乎只变成了一种概念,因为每一个需要clone的地方都是深拷贝。

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Git中的远程操作

    Git有很多优势,其中之一就是远程操作非常简便。本文详细介绍5个Git命令,它们的概念和用法,理解了这些内容,你就会完全掌握Git远程操作。

    刘亦枫
  • HTTP中的重定向

    URL 重定向,也称为 URL 转发,是一种当实际资源,如单个页面、表单或者整个 Web 应用被迁移到新的 URL 下的时候,保持(原有)链接可用的技术。HTT...

    刘亦枫
  • HTTP中的九个请求方法

    在 HTTP 协议中,CONNECT 方法可以开启一个客户端与所请求资源之间的双向沟通的通道。它可以用来创建隧道(tunnel)。

    刘亦枫
  • 【Spark篇】---Spark中Transformations转换算子

    Spark中默认有两大类算子,Transformation(转换算子),懒执行。action算子,立即执行,有一个action算子 ,就有一个job。

    LhWorld哥陪你聊算法
  • JavaWeb_常用功能_01_文件上传

     一个功能完善的JavaWeb应用,必不可少的一个功能就是文件的上传。无论是用户的头像等,还是用户需要上传的一系列资料,都是通过文件的上传功能实现的。

    shirayner
  • 房上的猫:StringBuffer类

    一.使用StringBuffer类  StringBuffer类位于java.lang包中,是String类的增强类  步骤:   1.声明StringBuff...

    房上的猫
  • Eclipse控制台不限日志行数

    Java学习123
  • 求助大佬:用sstap连不上是什么情况

    用xshell5弄好之后用sstap链接测试一直显示失败,端口全部开通也是不行,求助各位大佬,这个是什么情况,我已经试了一晚上了还是不行

    用户7017404
  • 网络时钟服务器(授时服务器)如何实现时间同步功能?

    某机场是某省的重要航空交通枢纽,是一个现代化的大型机场。机场内有电子钟94个,同时建设有离港系统、航显系统、广播系统、指挥调度系统、安检信息系统、楼宇自控系统、...

    NTP网络同步时钟
  • JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps、jstack、jmap、jhat、jstat等小...

    IT技术小咖

扫码关注云+社区

领取腾讯云代金券