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)
标签:arr,target,实现,js,对象,数组,var,拷贝 From: https://www.cnblogs.com/fxw1996/p/16992536.html