首页 > 编程语言 >JavaScript:对象:如何复制一个对象?浅拷贝与深拷贝

JavaScript:对象:如何复制一个对象?浅拷贝与深拷贝

时间:2022-12-09 19:00:47浏览次数:48  
标签:obj1 obj2 对象 JavaScript name1 拷贝 属性

回顾一下,我们对传参的讨论,对象的传参是引用传递,我们传递的是对象数据所在的内存地址;

那么无论我们怎么去赋值,所有变量指向的都是同一块内存;

image-20221209174903058

如上图所示,无论我去使用哪个变量去操作对象的属性,改变的始终是同一块内存区域的数据;

现在,我希望可以将obj1的内存数据,完整复制一份,存放到另一个内存区域obj2,使得这两块内存,保存的数据内容完全一样,但是我改变其中一块内存的数据,都不会影响到另一块内存的数据;

想一想,我们应该怎么做,才能达到这一目的?

浅拷贝

能想到的,是遍历对象的属性(基本数据类型),然后依次赋值给另一个对象的属性,因为说到复制,就是指值传递,只有基本数据类型是值传递:

image-20221209175729688

如上图所示,我们遍历了obj1的属性,并赋值给了obj2,我们修改了obj2的name1属性,但是并没有改变obj1的name1属性,证明我们成功复制了一份obj1的内存数据;

那我们每次都需要用for-in循环吗?JS有没有自带一些方法来实现浅拷贝呢?

有的:

  • Object.assign()方法

    语法为Object.assign(dest, src1, src2,,,,,)

    第一个变量dest是目标对象,即将后面的对象的属性值复制给目标对象;

    后面的所有变量src即是源对象,会将所有源对象的属性值全复制给目标对象,如果有属性名同名,则会进行覆盖;

    调用该方法,结果会返回dest;

    image-20221209181629699

深拷贝

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

image-20221209182402368

看上图,obj2对name1的name属性修改为了Bob,而obj1的name1的name属性,输出结果也为Bob,这意味着,obj1和obj2的name1属性指向的是同一块内存区域;

这是因为,对象是引用传递,我们在调用Object.assign()方法时,只是将obj1的name1的内存地址,复制给了obj2的name1,此时他们之间的内存关系,如下所示:

image-20221209183513255

也就是说,此时obj1和obj2并不完全互相独立,他们之间还共同管理着name1这块内存;

这种不完全互相独立的拷贝,我们称之为浅拷贝

所以,完全互相独立的拷贝,我们就称之为深拷贝

那么,我们怎样才能实现深拷贝,使两者完全互相独立呢?

可行的方法是,对name1这个对象,再进行一次浅拷贝。

这样太麻烦了,JS有没有自带的深拷贝的方法呢?

很遗憾,并没有。我们需要通过引入其他库,调用库方法,来进行深拷贝,这里不赘述。

标签:obj1,obj2,对象,JavaScript,name1,拷贝,属性
From: https://www.cnblogs.com/Journing/p/16969762.html

相关文章

  • synchronized的锁对象改变问题(转)
    原文:https://www.jianshu.com/p/f6b3cc21f5d7作者:跨界师 大家都知道synchronized是一个对象锁,所以当对象变化时,锁就会消失,就会没有同步效果。请看下面的问题:package......
  • python浅拷贝和深拷贝
    python浅拷贝和深拷贝python中对对象直接赋值其实只是将其换了一个名字,想要对对象进行真正的复制要通过别的方法。浅拷贝浅拷贝利用copy()函数就可以实现,它会产生新的对......
  • JavaScript:对象:如何读取、添加、删除对象的属性?
    如何给对象添加属性?直接对象名.属性名去添加属性直接对象名[属性名]去添加属性,此时属性名得是字符串类型,可以直接引号,也可以用变量名如何读取对象的属性值?这......
  • JavaScript:对象:如何去遍历输出一个对象的属性?语句for-in
    使用for-in的for循环语句,可以去遍历一个对象的属性,这类似于Java的增强for循环;但是注意,这并不能遍历对象的所有属性,有些隐藏的属性,是无法遍历出来的,虽然我们可以通过控制台......
  • Django 聚合分组、F对象的使用、聚合分组增加额外字段的方式
    DjangoQuerySet查询表达式F对象简单理解为可以通过F实现数据库操作,而非在Python内存中操作。通过F对象实现。filter()条件过滤或者对象级别的操作。让数据库,而不是......
  • JavaScript:箭头函数:省略写法
    之所以把箭头函数拎出来,是因为它不仅仅是声明函数的一种方式,它还是函数式编程的重要根基,它使得函数的使用更加的灵活,同时,它的语法,也相对于function声明的函数更加灵活和复......
  • JavaScript:箭头函数:作为参数进行传参
    之前已经说过,JS的函数,也是对象,而函数名是一个变量,是可以进行传参的,也即函数是可以被传参的。只要是函数,都可以被传参,但是箭头函数的语法更为灵活,所以更方便进行传参。如......
  • JavaScript:对象:如何创建对象?
    JS是面向对象的语言,除开基础数据类型,其他所有的数据类型都是对象,包括函数。如何去理解对象,什么是对象呢?举个例子,比如我们将日常生活中见到的猫这种动物,抽象成一个类Cat,这......
  • JavaScript:变量: 如何声明变量?
    声明变量可以用下面几种方式:但是这几种声明方式肯定是有区别的,主要是上面三种方式的区别,这需要结合window对象和作用域来说明,这里不赘述。声明变量的时候,推荐使用let,这......
  • JavaScript:变量:声明和赋值变量时,内存结构是什么样的?
    这里只是大概画出内存结构的模型图,方便理解当我们声明变量和赋值变量时,到底在干嘛。如上图所示,a赋值一个对象{},b赋值字符串hello;于是内存里划了三个区域给我们,一个存储......