浅拷贝和深拷贝都只针对于像Object, Array这样的复杂对象,
区别:浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制
如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化,这种叫浅拷贝。
深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个。
一、浅拷贝
1、数组的浅拷贝
(1)、可用concat、slice返回一个新数组的特性来实现拷贝
var arr = [‘old‘, 1, true, null, undefined];var new_arr = arr.concat(); // 或者var new_arr = arr.slice()也是一样的效果;new_arr[0] = ‘new‘;console.log(arr); // ["old", 1, true, null, undefined]console.log(new_arr); // ["new", 1, true, null, undefined]/2、
(2)、还有for循环也能实现数组的浅拷贝
var arr = [1,2,3,4,5]var arr2 = copyArr(arr)function copyArr(arr) { ???let res = [] ???for (let i = 0; i < arr.length; i++) { ????res.push(arr[i]) ???} ???return res}
(3)、ES6扩展运算符实现数组的浅拷贝
var arr = [1,2,3,4,5]var [ ...arr2 ] = arrarr[2] = 5console.log(arr)console.log(arr2)
但是如果数组嵌套了对象或者数组的话用concat、slice拷贝只要有修改会引起新旧数组都一起改变了,比如:
var arr = [{old: ‘old‘}, [‘old‘]];var new_arr = arr.concat();arr[0].old = ‘new‘;new_arr[1][0] = ‘new‘;console.log(arr); // [{old: ‘new‘}, [‘new‘]]console.log(new_arr); // [{old: ‘new‘}, [‘new‘]]
2、对象的浅拷贝
(1)、万能的for循环
var obj = { ?name: ‘FungLeo‘, ?sex: ‘man‘, ?old: ‘18‘}var obj2 = copyObj(obj)function copyObj(obj){ ?let res = {} ?for (var key in obj) { ???res[key] = obj[key] ?} ?return res}
(2)、ES6扩展运算符实现对象的浅拷贝
var obj = { ?name: ‘FungLeo‘, ?sex: ‘man‘, ?old: ‘18‘}var { ...obj2 } = objobj.old = ‘22‘console.log(obj)console.log(obj2)
同样如果对象里面还嵌套其他引入数据类型,对象的浅拷贝也无法做到真正的拷贝深层的东西
Object.assign()也可以对数组、对象实现浅拷贝
下面是浅拷贝一个通用方法,实现思路:遍历对象,把属性和属性值都放在一个新的对象里
var shallowCopy = function (obj) { ?// 只拷贝对象 ?if (typeof obj !== ‘object‘) return; ?// 根据obj的类型判断是新建一个数组还是一个对象 ?var newObj = obj instanceof Array ? [] : {}; ?// 遍历obj,并且判断是obj的属性才拷贝 ?for (var key in obj) { ???if (obj.hasOwnProperty(key)) { ?????newObj[key] = obj[key]; ???} ?} ?return newObj;}
二、深拷贝
下面是深拷贝一个通用方法,实现思路:拷贝的时候判断属性值的类型,如果是对象,继续递归调用深拷贝函数
var deepCopy = function(obj) { ?// 只拷贝对象 ?if (typeof obj !== ‘object‘) return; ?// 根据obj的类型判断是新建一个数组还是一个对象 ?var newObj = obj instanceof Array ? [] : {}; ?for (var key in obj) { ???// 遍历obj,并且判断是obj的属性才拷贝 ???if (obj.hasOwnProperty(key)) { ?????// 判断属性值的类型,如果是对象递归调用深拷贝 ?????newObj[key] = typeof obj[key] === ‘object‘ ? deepCopy(obj[key]) : obj[key]; ???} ?} ?return newObj;}
还有一种比较实用的深拷贝技巧:
function deepcopy(obj){ ???return JSON.parse(JSON.stringify(obj));}
但这种方法会存在一些缺陷,比如无法处理function,无法处理Reg,无法处理循环引用对象,但一般来说是够用的
js实现浅拷贝和深拷贝
原文地址:https://www.cnblogs.com/leelam/p/9515166.html