1,深拷贝与浅拷贝的区别
深拷贝:主要是将另一个对象的属性值拷贝过来之后,另一个对象的属性值并不受到影响,它自己在堆中开辟了自己的内存区域,不受外界干扰。
浅拷贝:主要拷贝的是对象的引用值,当改变对象的值,另一个对象的值也会发生变化。
2,常见的实现对象的深拷贝方法:
1)JSON.parse( JSON.stringify() ) 序列化和反序列
1 var obj = {
2 a: '123',
3 b: 234,
4 c: true,
5 d: null,
6 e: function() {console.log('test')},
7 h: new Set([4,3,null]),
8 i:Symbol('fsd'),
9 k: new Map([ ["name", "test"], ["title", "Author"] ])
10 }
11 console.log(JSON.stringify(obj));
12 // {"a":"123","b":234,"c":true,"d":null,"h":{},"k":{}}
可以看到data这个对象的属性里基本上包含了所有的数据类型,但通过JSON字符串化后,返回的值却有缺失,原因是JSON在执行字符串化的这个过程时,会先进行一个JSON格式化,获得安全的JSON值,因此如果是非安全的JSON值,就会被丢弃掉。其中undefined、function、symbol这三种类型的值就是非安全的(包括该对象的属性循环赋值该对象),所以格式化后,就被过滤掉了,而set、map这种数据格式的对象,也并没有被正确处理,而是处理成了一个空对象。
2)Object.assign(target, source1, source2)
es6新增的方法,可用于对象合并,将源对象的所有可枚举属性,复制到目标对象上。
1 var obj = {
2 a: '123',
3 b: 234,
4 c: true,
5 d: null,
6 e: function() {console.log('test')},
7 h: new Set([4,3,null]),
8 i:Symbol('fsd'),
9 k: new Map([ ["name", "test"], ["title", "Author"] ])
10 }
11 var newData = Object.assign({},obj)
12 console.log(newData)
注意:当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝
3)使用递归方法
1 deepClone(target) {
2 // 定义一个变量
3 let result;
4 // 如果当前需要深拷贝的是一个对象的话
5 if (typeof target === 'object') {
6 // 如果是一个数组的话
7 if (Array.isArray(target)) {
8 result = []; // 将result赋值为一个数组,并且执行遍历
9 for (let i in target) {
10 // 递归克隆数组中的每一项
11 result.push(this.deepClone(target[i]))
12 }
13 // 判断如果当前的值是null的话;直接赋值为null
14 } else if (target === null) {
15 result = null;
16 // 判断如果当前的值是一个RegExp对象的话,直接赋值
17 } else if (target.constructor === RegExp) {
18 result = target;
19 } else {
20 // 否则是普通对象,直接for in循环,递归赋值对象的所有值
21 result = {};
22 for (let i in target) {
23 result[i] = this.deepClone(target[i]);
24 }
25 }
26 // 如果不是对象的话,就是基本数据类型,那么直接赋值
27 } else {
28 result = target;
29 }
30 // 返回最终结果
31 return result;
32 },
4)lodash函数库实现深拷贝
1 let clone = cloneDeep(obj)
3,常见的实现数组的深拷贝方法:
1)for循环实现
1 var arr = [1,2,3,4,5]
2 var arr2 = copyArr(arr)
3 function copyArr(arr) {
4 let res = []
5 for (let i = 0; i < arr.length; i++) {
6 res.push(arr[i])
7 }
8 return res
2)slice方法 原理:将原数组中抽离部分出来形成一个新数组。只要设置为抽离全部,即可完成数组的深拷贝
1 var arr = [1,2,3,4,5]
2 var arr2 = arr.slice(0)
3 arr[2] = 5
4 console.log(arr)
5 console.log(arr2)
注意:
①没有参数的时候,是拷贝数组
②一个参数的时候,拷贝从起始位置到数组末尾的元素
③两个参数的时候,拷贝从起始位置到 结束位置的元素(不包含结束位置的元素,含头不含尾)
一维数组元素是深拷贝,数组元素二维以上是值的引用
3)concat方法 原理:用于连接多个数组组成一个新的数组的方法。那么,只要连接它自己,即可完成数组的深拷贝
1 var arr = [1,2,3,4,5]
2 var arr2 = arr.concat()
3 arr[2] = 5
4 console.log(arr)
5 console.log(arr2)
注意:只有在数组元素是一维的时候,是深拷贝,一维以上是对值的引用
4)ES6扩展运算符实现
1 var arr = [1,2,3,4,5]
2 var [ ...arr2 ] = arr
3 arr[2] = 5
4 console.log(arr)
5 console.log(arr2)