廣度優先遍歷實現js對象深拷貝

問題

通常咱們實現深拷貝都是用遞歸的方式,可是遞歸缺點就是容易內存泄漏,由於當js對象嵌套很深的層級的時候就容易出問題,那解決這個問題就能夠用循環的方式。廣度優先遍歷很適合作深拷貝,由於它是先遍歷完一層的數據後再遍歷下一層javascript

實現方法

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,
相關文章
相關標籤/搜索