问题

一般我们实现深拷贝都是用递归的方式,但是递归缺点就是容易内存泄漏,因为当js对象嵌套很深的层级的时候就容易出问题,那解决这个问题就可以用循环的方式。广度优先遍历很适合做深拷贝,因为它是先遍历完一层的数据后再遍历下一层

实现方法

 function isObject(val) {
            if (Object.prototype.toString.call(val) === '[object Object]') return true;
            return false;
        }
        function isArray(val) {
            return Array.isArray(val);
        }
        function isFunction(val){
            if (Object.prototype.toString.call(val) === '[object Function]') return true;
            return false;
        }
        function deepCopy(jsonObj) {
            if (!isArray(jsonObj) && !isObject(jsonObj)) return jsonObj;
            let copy = {};
            let queue = [];
            let visited = {};
            queue.push({
                key: 'root',
                value: jsonObj,
                parent: copy // 根节点parent就是copy
            });
        
            while (queue.length != 0) {
                const first = queue.shift();
                const parent = first.parent;
                if(visited[first.key] === first.value)continue;// 如果已将访问过则不处理
                if ((isArray(first.value) || isObject(first.value))) {
                    for (let [key, value] of Object.entries(first.value)) {
                        if (isArray(value) || isObject(value)) {
                            let childParent;
                            if (isObject(value)) {
                                childParent = {};
                            }
                            else if (isArray(value)) {
                                childParent = [];
                            }
                            queue.push({
                                key: key,
                                value: value,
                                parent: childParent // 重新声明一个parent
                            });
                            parent[key] = childParent;// 连接新的parent和旧的parent
                        }
                        else {
                            queue.push({
                                key: key,
                                value: value,
                                parent: parent
                            });
                        }
                    }
                } else {
                    parent[first.key] = first.value;
                }
                visited[first.key] = first.value;
            }
            return copy;

        }

测试

        let obj1 = {
            e: 2,
            a:{
                b:44
            }
        }
        // 模拟循环引用,并没有爆栈哦
        obj1.o = {
            m:obj1
        };
        const obj2 = deepCopy(obj1);
        obj1.a.b = 100;
       console.log(obj2.a.b)// 打印44,说明obj1的改变没有影响obj2,

fantasy525
586 声望18 粉丝

vue react,flutter,android