在探讨这个问题之前,首先得了解ECMAScript 的数据类型
ECMAScript 的数据类型
其次是堆和栈的区别
堆和栈的区别
其实深拷贝和浅拷贝的主要区别就是其在内存中的存储类型不同。
堆和栈都是内存中划分出来用来存储的区域。
栈(stack)为自动分配的内存空间,它由系统自动释放。
堆(heap)内存是动态分配的内存,大小不定也不会自动释放。一般由程序员分配释放,若程序员不释放,程序结束时可能由垃圾回收机制回收。
基本(原始)数据类型(Undefined、Null、Boolean、Number、String)的值直接保存在栈中
引用(复杂)数据类型(对象、数组和函数)的值保存在堆中,通过使用在栈中保存对应的指针来获取堆中的值。
对原数据影响
– | 和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
总结
浅拷贝
浅拷贝指的是将一个对象的属性值复制到另一个对象,如果有的属性的值为引用类型的话,那么会将这个引用的地址复制给对象,因此两个对象会有同一个引用类型的引用。所以说,浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。
深拷贝
深拷贝相对浅拷贝而言,如果遇到属性值为引用类型的时候,它新建一个引用类型并将对应的值复制给它,因此对象获得的一个新的引用类型而不是一个原有类型的引用。
实现方式
浅拷贝
1.Object.assign(target, ...sources)
1 | let a = { |
2.扩展运算符 ...
1 | let a = { |
3.遍历+hasOwnProperty()
1 | // 浅拷贝的实现; |
深拷贝
1.JSON.parse(JSON.stringify(object))
1 | let a = { |
但是该方法也是有局限性的:
- 会忽略
undefined
- 会忽略
symbol
- 不能序列化函数
- 不能解决循环引用的对象
2.递归+hasOwnProperty()
1 | // 深拷贝的实现; |
参考文章