深浅拷贝区别
我们都知道JS
中有两种数据类型,一种是基本数据类型,一种是引用数据类型,基本数据类型是按值访问的,即在操作基本类型的变量时,是直接修改变量的值,而引用数据类型的值是按引用访问的,什么是按引用访问的呢? JS
的引用类型,也叫对象类型,是保存在内存中的,而在JS
中又无法直接操作内存中的对象,实际上操作的是对象的引用,因此在引用类型变量在进行复制操作时,并不是对对象值的直接复制,而是将对象的引用复制给了另一个变量,实际上变量指向的是同一个内存地址中对象的值,因此只要改变其中一个对象变量的值,另外一个就会一起改变,这就是浅拷贝。
在深拷贝中,会开辟一个新的内存地址用来存放对象的值,两个对象对应两个不同的内存地址,修改一个对象并不会对另一个对象产生影响。
浅拷贝
实现浅拷贝的方法
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,它将返回目标对象。
注意:Object.assign()拷贝的是属性值,假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
Array.prototype.slice()方法提取并返回一个新的数组,如果原数组中的元素是个对象的引用,slice会拷贝这个对象的引用到新的数组
Array.prototype.concat()用于合并多个数组,并返回一个新的数组,和slice方法类似,当原数组中的元素是个对象的引用,concat在合并时拷贝的就是这个对象的引用。
深拷贝
深拷贝最简单粗暴的方法就是JSON.Stringify()和JSON.Parse()的混合配对使用,这个方法确实可以实现深拷贝,在新对象中修改对象的引用时,并不会影响老对象里面的值, 但在JSON.Stringify()做序列时,如果源对象中有undefined、function、symbol时,做序列化会被忽略,导致拷贝生成的对象中没有对应属性和属性值。
第二种方法 递归
对需要拷贝的对象的属性进行递归遍历,如果对象的属性不是基本类型时,就继续递归,知道遍历对象属性为基本类型,然后将属性和属性值赋给新对象。
第三种方法是:利用第三方工具库实现 例如:lodash