首先明确一点,浅拷贝和深拷贝的概念,是因为栈堆内存的设计产生了,所以
Java
、JavaScript
、Python
等等,都是有这个概念的!
为了方便,我就直接拿JS
来演示了。
创建对象
首先创建一个对象。
var obj = {
a: 1,
b: 2,
c: {
d: 3,
e: 4,
}
};
这个对象中,还有一个子对象,也就是obj
对象中存在对象c
。
因为如果我们单纯一个对象,js
是体现不出来这个浅拷贝与深拷贝的区别的。
如何去实现浅拷贝与深拷贝我就不说了,因为每个语言实现方法不一样,尤其
JavaScript
可实现方法太多,库也是一大堆,原理说清楚,啥语言都不是问题。
拷贝
//浅拷贝obj
var obj1 = Object.assign({}, obj);
//深拷贝obj
var obj2 = JSON.parse(JSON.stringify(obj));
修改拷贝后对象参数
//修改浅拷贝对象参数的值
obj1.c.d = 5;
//修改深拷贝对象参数的值
obj2.c.e = 6;
注:obj1
和obj2
都是拷贝了obj
对象的内容。
此时可能还没有什么差别体现,我们输出一下就明白了。
输出查看差别
console.log('原对象',obj);
console.log('浅拷贝后对象',obj1);
console.log('深拷贝后对象',obj2);
看图——>注:我这里是ts
写,运行也是用ts-node
直接运行,其他语言用其他语言方法。
结果如下:
原对象 { a: 1, b: 2, c: { d: 5, e: 4 } }
浅拷贝后对象 { a: 1, b: 2, c: { d: 5, e: 4 } }
深拷贝后对象 { a: 1, b: 2, c: { d: 3, e: 6 } }
//注意看原来定义对象参数
var obj = {
a: 1,
b: 2,
c: {
d: 3,
e: 4,
}
};
看看输出后原对象参数——>???为什么输出的原对象的d
的值变成了5
?
再想想,我们是不是给浅拷贝的d
重新赋值了个5
?
思考——>为什么这个
5
不仅仅是赋值到了obj1
,也就是浅拷贝后对象上,还
赋值到了原对象
即obj
上。原因是,
obj1
中c
这个对象其实不是复制
一份obj
中的c
,而是引用
!!!也就是
obj1
和obj
中的c
都是指向了——>obj
对象创建时在栈堆内存
中c
对象。
我画个图,凑合看看吧:
obj
和obj1
中的c
对象,最终都是指向同一个
内存地址。
那既然指向是同一个,那自然改了obj1
中的c
,obj
的c
也改了。
注意!那深拷贝
就相反
,深拷贝它是直接复制
的。
它里面的c
也是直接新开辟
了一个内存,而不是obj
原来的c
的那块内存,所以obj的c != obj2的c
。
那你可能会问,怎么样证明是不是同一个呢?
简单!输出一下不就知道了:
console.log(obj.c === obj1.c);
console.log(obj.c === obj2.c);
结果如下:
true
false
可以看出,obj1
的c
指向的内存与obj
的c
相同,而obj2
的c
指向的内存与obj
的不同。
所以,深拷贝
中的c
对象值改变不会影响
到原来对象。浅拷贝会影响
。