数据类型
- Number
- String
- Boolean
- Null
- Undefined
- Symbol
- Object
其中前面6种类型是原始数据类型,而Object
是引用数据类型我更喜欢把前面6种称之为简单数据类型,而把Object
称之为复杂数据类型。因为简单数据类型没有子类型了,不可以再进行拆分了,而复杂数据类型还有子类型,比如Array
,Function
,RegExp
,Date
等对象,正是因为这些子类型的不同导致了深拷贝的各种问题。这就是为什么很多人在回答有哪些基本数据类型时会把Array和Function答进去。事实上他们只是Object的子类型,并不是基本数据类型。
数据类型的不同,会导致在内存中的存储方式的不同,如果是简单数据类型,存储在栈空间中,存储的是一个值;如果是复杂数据类型,存储在堆空间中,存储的是一个引用,正是这种存储方式的差异,导致了浅拷贝和深拷贝的区别。
浅拷贝和深拷贝
我们先来明确一下到底什么是浅拷贝什么是深拷贝
浅拷贝: 如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以修改新拷贝的对象会影响原对象。
这些都是官方的一些定义,他们喜欢用内存地址这种不直观的方式来进行描述,我希望能够用简单的图来描述清楚。
如上图所示:所谓的浅拷贝就是无论你拷贝多少个对象,这些拷贝的对象里面的属性还是指向原来对象里面的属性。从图上线来看,就是两个对象之间线相交。 正是因为线的相交导致互相影响,因此只要有一个对象修改了属性,其他对象对应的属性都会进行修改。
1 | let obj = { |
官方描述深拷贝: 将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
我理解的深拷贝——图上线之间不存在相交的就是深拷贝:
我们可以看到,深拷贝一个对象,就是创建一个与之前对象完全无关的对象,从图上线来看,就是两个对象之间线不相交。由于两个对象之间完全不相交(用句俗语来说就是咱两是两条平行线,永远也扯不上关系),既然扯不上关系,因此也就不存在谁影响谁的问题了。
1 | let obj = { |
上面的代码中obj2
是通过深拷贝obj1
得到的,修改obj2
的属性,发现Obj1
的属性不会跟着修改。这是深拷贝。
作者:海因斯坦
链接:https://juejin.im/post/6889327058158092302
来源:掘金