通常咱們實現深拷貝都是用遞歸的方式,可是遞歸缺點就是容易內存泄漏,由於當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,