深拷贝和浅拷贝

深拷贝和浅拷贝的理解与应用

对象拷贝(object Copy)就是讲一个对象的属性拷贝到另一个有着相同类类型的对象中去。

在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复制对象的部分或者全部数据,JavaScript中有两种类型的对象拷贝:深拷贝(Deep Copy)、浅拷贝(Shallow Copy)。

首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。

深拷贝和浅拷贝的区别

浅拷贝 —只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

深拷贝 —在计算机中开辟了一块新的内存地址用于存放复制的对象

深拷贝通俗易懂的理解就是:b通过a分享的链接买了一件和a一样的衣服,但是a和b的衣服确是两件长得一样的衣服,不管a的衣服是脏了还是破了都不会影像b的衣服

一、基本类型和引用类型的区别

1、先了解内存

   任何编程语言的内存分区几乎都是一样的

       内存是存储数据的,不同类型的数据要存储在不同的区域,即分类存放,不同的区域作用和功能也不一样。就像你家里的衣柜一样,也分了不同的区域:如挂西装的区域,放袜子的区域等等,我相信每个人都会把这两个东西放在不同的区域。要不然,当你西装革履地参加一个高档的宴会,手塞在裤兜里,掏出来一只臭袜子,是不是很尴尬!!!哈哈!!!

以下为内存的分区图。内存分为四个区域:栈区(堆栈),堆区,全局静态区,只读区(常量区和代码区)。

2、基本类型和引用类型在内存上存储的区别

现在只看栈区和堆区,不管其它区域,也假定只是局部变量。

3、到底什么是基本类型和引用类型

      1)、基本类型:就是值类型,即在变量所对应的内存区域存储的是值,如:上面的age变量所对应的内存存储的就是值250.

      2)、引用类型:就是地址类型。

   何为地址:地址就是编号,要地址何用,就是为了容易找到。每个人的家里为什么要有一个唯一的地址,就是在邮寄时,能够找到你家。

浅拷贝的逻辑:

 深拷贝逻辑:

什么是可变对象,什么是不可变对象:

可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值;

不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象指向的值复制出来一份,然后做了修改后存到另一个地址上了,但是可变对象就不会做这样的动作,而是直接在对象所指的地址上把值给改变了,而这个对象依然指向这个地址。

深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:

浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

也可以这样理解:

深拷贝就是完全跟以前就没有任何关系了,原来的对象怎么改都不会影响当前对象

浅拷贝,原对象的list元素改变的话会改变当前对象,如果当前对象中list元素改变了,也同样会影响原对象。

浅拷贝就是藕断丝连

深拷贝就是离婚了

通常复制的时候要用深拷贝,因为浅拷贝后,两个对象中不可变对象指向不同地址,相互不会改变,但是两个对象中的可变元素是指向相同的地址,一个变了,另一个会同时改变,会有影响(list是可变对象)。

如果要让原list和copy list没有影响怎么办?

用深拷贝,拷贝后完全开辟新的内存地址来保存之前的对象,虽然可能地址执行的内容可能相同(同一个地址,例如’s’),但是不会相互影响。

比如:

a = [1,2,3,[1,2,3,[5,6]]

b=a #这个时候是赋值,所以指向的地址是同一个地址

浅拷贝只能是复制到第一层的,更深层次的路径数据,还是指向原来的路径

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝

所以浅拷贝数据之后,需要修改更深层次的数据的时候,修改的还是原来路径的数据,相互之间是有影响的

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9

所以浅拷贝数据之后,需要修改浅层次(第一层)的数据的时候,修改的是复制之后的数据,与原来的数据相互之间不影响的。

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0

 深拷贝,就是所以的路径的数据全部都重新在复制一层,两组数据之间完全不影响,相互之间修改的时候也互不干扰。

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0
d = copy.deepcopy(a) #深拷贝

 在修改深拷贝的数据的时候跟源数据是没有影响的

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0
d = copy.deepcopy(a) #深拷贝
d[3][0] = 100

  深拷贝之后的修改相互之间完全独立

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0
d = copy.deepcopy(a) #深拷贝
d[3][3][0] = 100

 深拷贝之后的修改相互之间不会受到影响

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0
d = copy.deepcopy(a) #深拷贝
d[3][3][0] = 100
c[3] = [0,1,2,3]

可变对象和不可变对象

import copy

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0
d = copy.deepcopy(a) #深拷贝
d[3][3][0] = 100
c[3] = [0,1,2,3]

#不可变对象
e = 1
f = e

 列表可以使用copy,其他的不可变元素是不可以的。因为相互之间是不能被改变的,所以有在多的指向这个元素的时候都不影响的。

import copy

a = [1,2,3,[1,2,3,[5,6]]
b=a
c = a.copy()  #浅拷贝
c[3][0] = 9
c[1] = 0
d = copy.deepcopy(a) #深拷贝
d[3][3][0] = 100
c[3] = [0,1,2,3]

#不可变对象
e = (1,2)  #元组
f = e

通常来讲不可变元素包含:

int,float,complex,long,str,unicode,tuple

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值