如何在不使用递归、JSON.parse \ JSON.stringify、structuralClone()的情况下实现深拷贝。一个对象中可以有任意数量的元素。
const data1 = {
a: 10,
y: null,
k: [1, 2],
b: 3,
c: {
d: 4,
e: {
w: 50,
u: undefined,
s: {
f: {
v: 5,
},
},
},
},
};
const data2 = [
{
a: 10,
y: null,
k: [1, 2],
b: 3,
c: {
d: 4,
e: {
w: 50,
u: undefined,
s: {
f: {
v: 5,
},
},
},
},
};
];
在我的示例中,我无法实现深层复制,我只是在第二个循环处停止。我们怎样才能避免递归和其他现成的解决方案?
function deepCopy(dataType) {
const copy = {};
let data = dataType;
if (Array.isArray(data)) {
data = dataType[0];
}
for (const [key, value] of Object.entries(data)) {
if (typeof data[key] === "object") {
copy[key] = Array.isArray(data[key]) ? [] : value;
for (let deepKey in data[key]) {
copy[key][deepKey] = data[key][deepKey];
}
} else {
copy[key] = data[key];
}
}
return copy;
}
如果使用堆栈和引用查找图,则可以迭代该结构而无需任何递归。
这是一个细分:
判断传入的对象是否是对象,如果不是则立即返回
创建一个堆栈,其中源作为对象,目标与对象类型相同
此外,创建一个引用映射,将原始对象引用映射到目标副本
当堆栈不为空时:
从堆栈中删除项目
循环对象中的所有键(或数组索引):
如果该值是一个对象:
否则,分配值
const data1 = {
a: 10,
y: null,
k: [1, 2],
b: 3,
c: {
d: 4,
e: {
w: 50,
u: undefined,
s: { f: { v: 5 } }
}
}
};
const data2 = deepCopy(data1);
// Objects are not the same reference
console.log(data1.c !== data2.c); // true
console.log(data1.c.e !== data2.c.e); // true
console.log(data1.c.e.s.f !== data2.c.e.s.f); // true
console.log(data2); // Print the copy
function deepCopy(dataType) {
const isObject = (value) => typeof value === 'object' && value !== null;
const targetFrom = (source) => Array.isArray(source) ? [] : {};
if (!isObject(dataType)) { return dataType; }
const stack = [{ source: dataType, target: targetFrom(dataType) }];
const refMap = new Map([[dataType, stack[0].target]]);
while (stack.length) {
const { source, target } = stack.pop();
for (const key in source) {
if (source.hasOwnProperty(key)) {
const value = source[key];
if (isObject(value)) {
if (!refMap.has(value)) {
const newTarget = targetFrom(value);
refMap.set(value, newTarget);
stack.push({ source: value, target: newTarget });
}
target[key] = refMap.get(value);
} else {
target[key] = value;
}
}
}
}
return refMap.get(dataType);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }