问题
一般我们实现深拷贝都是用递归的方式,但是递归缺点就是容易内存泄漏,因为当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,
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。