js深拷贝与循环引用
在 JavaScript 中,深拷贝(deep copy)意味着创建一个新的对象,并递归地复制原始对象的所有属性,包括嵌套的对象和数组。深拷贝确保原始对象和副本之间不共享任何引用,因此修改副本不会影响原始对象。
然而,当原始对象中存在循环引用时,深拷贝的实现可能会变得复杂。循环引用是指两个或多个对象相互引用,形成一个闭环。在这种情况下,深拷贝函数需要能够识别并处理循环引用,以避免无限循环。
function deepCopy(target) {
var arr = []; // use array store the used refrence, and avoid repeat
return _deepCopy(target);
function _deepCopy(target) {
let result = {};
for (let k in target) {
if (target.hasOwnProperty(k)) {
if (target[k] && typeof target[k] === 'object') {
if ((arr.filter(v=>v === target[k])).length === 0) {
arr.push(target[k]);
result[k] = _deepCopy(target[k]);
}
} else {
result[k] = target[k];
}
}
}
return result;
}
}
// test code
var a = {
n: 1,
m: 2
};
var b = {
m: 1,
n: 2
};
a.b = b;
b.a = a;
var c = deepCopy(a);
另外,我们可以在深拷贝函数中使用一个映射(如 Map 或 WeakMap)来跟踪已经拷贝过的对象。以下是一个处理循环引用的深拷贝函数的示例:
function deepCopy(obj, map = new WeakMap()) {
if (obj === null) return null; // 处理 null 值
if (typeof obj !== 'object') return obj; // 处理非对象值
if (map.has(obj)) return map.get(obj); // 处理循环引用
const clone = Array.isArray(obj) ? [] : {};
map.set(obj, clone); // 记录当前对象的副本
Object.keys(obj).forEach((key) => {
clone[key] = deepCopy(obj[key], map); // 递归拷贝对象的属性
});
return clone;
}