在实际开发中,如果遇到稍微复杂一点的逻辑,经常会遇到要复制对象或数组的场景。而在复制之后,我们会发现改了副本,原对象或数组的数据也相应改变了。这就是深拷贝的问题。
其原理涉及到内存,简单来说,我们的浅拷贝就是新建一个变量,指向目标变量,而不占用新的内存,所有一旦改变,就是直接改变的内存中的值,所以原来的值也改变了。
深拷贝就是,启用新的内存,所以修改新的值,将不影响旧的值。
会产生新内存的一些常用公共方法:
concat,slice
比如,var new_arr = arr.concat();var new_arr = arr.slice()
原本以为这样就可以一劳永逸,直到遇到一个无限嵌套循环的数组的场景。
结构如上。我们使用上边两个方法进行深拷贝之后,发现,改动一级不会影响原数据,但是改动了内部二级数据之后,原数据就变了。
解决办法:
1.对象-字符-对象转化,适用于对象和数组,不适用于方法
var new_arr = JSON.parse(JSON.stringify(arr))
2.递归深拷贝
代码 :
1 var deepCopy = function(obj) { 2 // 只拷贝对象 3 if (typeof obj !== 'object') return; 4 // 根据obj的类型判断是新建一个数组还是一个对象 5 var newObj = obj instanceof Array ? [] : {}; 6 for (var key in obj) { 7 // 遍历obj,并且判断是obj的属性才拷贝 8 if (obj.hasOwnProperty(key)) { 9 // 判断属性值的类型,如果是对象递归调用深拷贝10 newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];11 }12 }13 return newObj;14 }
附封装的浅拷贝方法:
1 var shallowCopy = function (obj) { 2 // 只拷贝对象 3 if (typeof obj !== 'object') return; 4 // 根据obj的类型判断是新建一个数组还是一个对象 5 var newObj = obj instanceof Array ? [] : {}; 6 // 遍历obj,并且判断是obj的属性才拷贝 7 for (var key in obj) { 8 if (obj.hasOwnProperty(key)) { 9 newObj[key] = obj[key];10 }11 }12 return newObj;13 }