Open Reaper622 opened 5 years ago
补充一个深拷贝没有考虑到的问题: 循环引用
即当一个对象内部引用它本身时,会存在超出最大执行栈的问题,此时我们可以使用一个Map
来记录已经读取过的引用。
function deepCopy3(obj, map = new Map()) {
if (map.get(obj)) {
return obj;
}
let result = Array.isArray(obj) ? [] : {};
map.set(obj, true)
for(let i in obj) {
if (obj.hasOwnProperty(obj[i])) {
if ( typeof obj[i] === 'object' && obj[i] !== null) {
result[i] = deepCopy3(obj[i], map)
} else {
result[i] = obj[i];
}
}
}
return result;
}
但此时又存在了另一个问题,那就是Map
结构内的key
与value
是强引用,所谓强引用,即能够确保其引用的对象不会被垃圾回收。拿上面得例子来说,执行深拷贝后,map
和obj
就产生了强引用,此时obj
的所占用的内存空间直到程序结束才会释放。
针对这个问题,ES本身也给我们提供了解决方案——WeakMap
,整体操作与Map
相同,只是内部为弱引用,它的键必须为对象,值可以为任意类型。此时我们可以对上面的深拷贝函数加以完善:
function deepCopy3(obj, map = new WeakMap()) {
if (map.get(obj)) {
return obj;
}
let result = Array.isArray(obj) ? [] : {};
map.set(obj, true)
for(let i in obj) {
if (obj.hasOwnProperty(obj[i])) {
if ( typeof obj[i] === 'object' && obj[i] !== null) {
result[i] = deepCopy3(obj[i], map)
} else {
result[i] = obj[i];
}
}
}
return result;
}
JS 对象的深浅拷贝
深浅拷贝区别
浅拷贝的实现方法
深拷贝实现方法