通常咱们实现深拷贝都是用递归的方式,可是递归缺点就是容易内存泄漏,由于当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,