此代码来自https://javascript.info/object-copy
function cloneDeep(obj) {
let clone = {};
for (let key in obj) {
if (typeof obj[key] === "object") {
clone[key] = cloneDeep(obj[key]);
} else {
clone[key] = obj[key];
}
}
return clone;
}
let user = {
name: "John",
sizes: {
height: 182,
width: 50,
},
};
console.log(cloneDeep(user));
我不太明白这个递归在第 5 行是如何工作的。对于 obj 中的每个键(所以高度和大小),如果对象中有一个对象,它会再次运行 cloneDeep()
EACH TIME 。在第 2 行,它再次初始化 clone = {}。
如果它的高度和宽度都运行 cloneDeep()
,我无法理解为什么输出不是这样的:
{name: "John",
sizes: {height: 182},
sizes: {width: 50}
}
答案 0 :(得分:3)
你应该把这看作是一个树数据结构问题,一个对象有 x 个子属性,每个子属性有 x 个更多的子属性,依此类推……对于每个孩子,都有一个由这个孩子生成的特定子树,所以你可以为每个孩子递归调用这个函数,因为每个孩子都有自己的属性树。要进一步了解此类算法,您应该查看Trees。
答案 1 :(得分:1)
考虑一个 clone
函数,它可以正确地切换对象和数组 -
function clone(t)
{ switch(t?.constructor)
{ case Array:
return t.map(v => clone(v))
case Object:
return Object
.entries(t)
.reduce
( (r, [k, v]) =>
Object.assign(r, {[k]: clone(v)})
, {}
)
default:
return t
}
}
现在我们设置一个 original
对象和该对象的 copy
-
const original =
{a: [{b:1}, {c:2}], d: {e: "f"}}
const copy =
clone(original)
如果我们对 original
进行一些更改 -
original.a[0].b = 11
original.a[1].c = 22
original.a.push({z:3})
original.d.e = "ff"
它们不应出现在 copy
-
console.log(original)
// {"a":[{"b":11},{"c":22},{"z":3}],"d":{"e":"ff"}}
console.log(copy)
// {"a":[{"b":1},{"c":2}],"d":{"e":"f"}}
展开下面的代码片段以在您自己的浏览器中验证结果 -
function clone(t)
{ switch(t?.constructor)
{ case Array:
return t.map(v => clone(v))
case Object:
return Object
.entries(t)
.reduce
( (r, [k, v]) =>
Object.assign(r, {[k]: clone(v)})
, {}
)
default:
return t
}
}
const original =
{a: [{b:1}, {c:2}], d: {e: "f"}}
const copy =
clone(original)
// changes to original
original.a[0].b = 11
original.a[1].c = 22
original.a.push({z:3})
original.d.e = "ff"
console.log(JSON.stringify(original))
// {"a":[{"b":11},{"c":22},{"z":3}],"d":{"e":"ff"}}
console.log(JSON.stringify(copy))
// {"a":[{"b":1},{"c":2}],"d":{"e":"f"}}
答案 2 :(得分:0)
对那里正在发生的事情的象征性表示
let user = { // is object, init cloneDeep0.clone0:{}
name: "John", // not object, set clone0 key/value clone0={name: "John"}
sizes: { // is object, init cloneDeep1.clone1:{}
// set clone0 key/(clone1={}), clone0={name: "John", sizes: (clone1={}}}
height: 182, // not object, set clone1 key/value clone0={name: "John", sizes: (clone1={height: 182})}
width: 50, // not object, set clone1 key/value clone0={name: "John", sizes: (clone1={height: 182, width: 50})}
},
};
// return clone0={name: "John", sizes: (clone1={height: 182, width: 50})}
实际上该代码中有一个错误,它会将 null
值克隆为 {}