JS 深拷贝循环引用问题解析

2025-12-22 2405阅读

在 JavaScript 中,深拷贝是一个常见的操作,它用于创建一个与原始对象完全独立的副本。然而,当对象中存在循环引用时,普通的深拷贝方法就会遇到问题。

循环引用的概念

循环引用指的是对象之间相互引用,形成一个闭环。例如:

let obj1 = {};
let obj2 = {};
obj1.other = obj2;
obj2.other = obj1;

在这个例子中,obj1obj2 相互引用,形成了循环引用。

普通深拷贝方法的局限

常见的深拷贝方法如 JSON.parse(JSON.stringify()),在遇到循环引用时会报错。因为 JSON.stringify 无法处理循环引用。

解决循环引用的深拷贝实现

我们可以通过递归的方式,并借助一个 WeakMap 来记录已经拷贝过的对象,从而解决循环引用问题。以下是一个简单的实现:

function deepClone(obj, map = new WeakMap()) {
    if (typeof obj!== 'object' || obj === null) {
        return obj;
    }
    if (map.has(obj)) {
        return map.get(obj);
    }
    let cloneObj;
    if (Array.isArray(obj)) {
        cloneObj = [];
    } else {
        cloneObj = {};
    }
    map.set(obj, cloneObj);
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            cloneObj[key] = deepClone(obj[key], map);
        }
    }
    return cloneObj;
}

在这个函数中,首先判断 obj 是否为对象或 null,如果不是直接返回。然后检查 WeakMap 中是否已经存在该对象的拷贝,如果有则返回。接着根据 obj 的类型创建相应的空对象(数组或普通对象),并将原始对象和拷贝对象存入 WeakMap。最后通过递归遍历 obj 的属性,进行深拷贝。

示例验证

let obj1 = {};
let obj2 = {};
obj1.other = obj2;
obj2.other = obj1;
let clone = deepClone(obj1);
console.log(clone);

通过这个示例可以看到,我们成功地对包含循环引用的对象进行了深拷贝。

总结

在 JavaScript 中处理深拷贝循环引用问题,需要我们深入理解对象的引用关系,并借助合适的数据结构(如 WeakMap)来记录已拷贝的对象,避免无限递归。通过上述的实现方法,我们能够更稳健地进行深拷贝操作,确保在复杂对象结构(包括循环引用)下也能得到正确的结果。掌握深拷贝循环引用的处理,对于编写高质量的 JavaScript 代码,处理复杂数据结构至关重要。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

目录[+]