区别
浅拷贝
- 对于字符串类型,浅拷贝是对值的复制;
- 对于对象或数组来说,浅拷贝是对
对象地址的复制
,并没有开辟新的栈。就是将一个对象的内存地址的“编号”拷贝给另一个对象。只复制一层对象的属性
.
深拷贝
- 实现原理: 先新建一个空对象,
内存中新开辟一块地址
,把被复制对象的所有可枚举的(注意可枚举的对象)属性方法
一一复制过来,注意要用递归来复制子对象里面的所有属性和方法,直到子子…..属性为基本数据类型。
总结
深拷贝理解两点:1. 新开辟内存地址,2,递归来刨根复制。
实现
浅拷贝
在Javascript 中,将一个对象赋值给一个变量其实只是将这个对象的引用拷贝了一份
假设这么一段代码1
2
3
4
5var man = {
name: 'aepkill',
sex: 'male'
};
var superMan = man;
并没有创建一个新的对象实体,而是仅仅拷贝了这种引用关系。
所以假设执行 man.name = ‘aotuman’ ,那么superMan.name的值也会变成 ‘aotuman’,因为其实他们引用的是同一个对象实体。
很多场景下并不希望出现像上面中那样, 我们希望能使两个变量相互独立,不再引用同一个对象
这很容易实现,只需要申明一个新的对象,然后将这个对象的所有字段原封不动拷贝过去即可:
1 | function copy(obj){ |
两个变量已经不在引用同一个对象,二者的修改是相互独立的
深拷贝
上面已经完成了基本的拷贝,但是只拷贝了第一层的关系,如果对象不止一层的话,上面的函数就不适用了:
1 | var people = { |
因为只拷贝了一层,所以people 与 hero 中的concat 字段还是引用同一个对象,所以当执行 people.concat.tel = ‘1111111111’ 后,hero .concat.tel 也变成了 ‘1111111111 ‘ ,该如何解决这个问题呢?
此时,需要对这个问题进行梳理并抽象:定义一个函数deepCopy,该函数遍历传入的对象,如果该字段的值不是一个对象则可直接赋值给新对象,否则对该字段用函数deepCopy进行递归操作。
1 | function deepCopy(obj) { |
OK,deepCopy 函数可以拷贝任意深度的对象了