我有一个JavaScript对象,让我们称它为“obj”。我想遍历这个对象及其后代,并找出每个对象有多少个后代,并在对象的属性上保存这个数字,如obj.numOfDescendants
或其他东西。如何以递归方式完成?
我尝试了以下操作,但它没有工作:
var traversTree = function(obj) {
for (let k in obj) {
if (typeof obj[k] === "object") {
if (!obj["numOfDescendants"])
obj["numOfDescendants"] = 0;
obj.numOfDescendants += traversTree(obj[k]); // Here is where I'm stuck.
// What do I return here
// in order to sum the
// depth?
return 1;
}
}
}
有人指出我错了吗?
答案 0 :(得分:2)
一些问题:
您希望traversTree
返回一个值:
obj.numOfDescendants += traversTree(obj[k]);
...但在所有情况下,您都没有从中返回值,仅在某些情况下。您希望函数始终返回值。
在循环结束之前,你过早地回来了。您需要在对象的对象孩子的所有上添加调用traversTree
的结果。
(与上一点相关。)您在循环中重新更新obj.numOfDescendants
,但在循环结束之前,您实际上并不知道该数字。
我们需要计算我们刚刚输入的那个,所以在添加后代时,我们需要在其上调用traversTree
和 1的结果。
这就是:
var traversTree = function(obj) {
var descendants = 0;
for (let k in obj) {
if (typeof obj[k] === "object") {
descendants += traversTree(obj[k]) + 1;
}
}
obj.numOfDescendants = descendants;
return descendants;
};
示例:
var traversTree = function(obj) {
var descendants = 0;
for (let k in obj) {
if (typeof obj[k] === "object") {
descendants += traversTree(obj[k]) + 1;
}
}
obj.numOfDescendants = descendants;
return descendants;
};
console.log("Example 1:");
var o1 = {
test: {}
};
traversTree(o1);
console.log(o1);
console.log("Example 2:");
var o2 = {
a: {},
b: {
c: {}
}
};
traversTree(o2);
console.log(o2);
console.log("Example 3:");
var o3 = {
a: {},
b: {
c: [{}, {x:{z:"y"}}, {}]
}
};
traversTree(o3);
console.log(o3);

.as-console-wrapper {
max-height: 100% !important;
}

附注:您已在代码中同时使用var
和let
。 let
是ES2015的新关键字。如果您正在使用ES2015或更高版本并切换到使用let
,那么最好始终如一地执行此操作,而不是有时使用var
。另请参阅尽可能使用const
和箭头函数,例如:
const traversTree = obj => {
let descendants = 0;
for (const k in obj) {
if (typeof obj[k] === "object") {
descendants += traversTree(obj[k]) + 1;
}
}
obj.numOfDescendants = descendants;
return descendants;
};
上面的const
看k
可能看起来很奇怪,但是在初始值设定项中声明迭代器变量时for
循环的机制实际上是这样的每个循环迭代都有一个新的k
,k
的值在循环体中永远不会改变,所以const
实际上在那里工作。但是,当然,它看起来有点奇怪。