JavaScript递归函数无法返回指定节点所有子孙节点问题
解决递归获取子孙节点无法正确返回结果的问题
你的递归函数能生成所需的节点列表,但因为未正确处理递归返回值、缺少最终返回语句,且遗漏了目标节点本身的收集,导致无法输出正确结果。以下是问题分析和修正方案:
问题根源
- 原函数未将传入
id对应的目标节点加入结果列表,只收集了它的子节点; - 递归调用时未处理返回值,且最后没有返回结果数组,导致外层调用得到
undefined; - 使用
result = [...result, ...childrens]重新赋值数组,破坏了递归中数组的引用传递,子递归的修改无法同步到外层。
修正方案一:更简洁的递归写法
let data = [ // 原数据保持不变 { "nodeId": "root", "name": "ROOT", "parentNodeId": null }, { "nodeId": "1", "name": "one", "parentNodeId": "root" }, { "nodeId": "2", "name": "Two", "parentNodeId": "1" }, { "nodeId": "31", "name": "three", "parentNodeId": "2" }, { "nodeId": "32", "name": "three-2", "parentNodeId": "2" }, { "nodeId": "33", "name": "three-3", "parentNodeId": "2" }, { "nodeId": "41", "name": "four 2-1", "parentNodeId": "32" }, { "nodeId": "51", "name": "five 2-1-1", "parentNodeId": "41" }, { "nodeId": "61", "name": "six 2-1-1-1", "parentNodeId": "51" }, { "nodeId": "62", "name": "six 2-1-1-2", "parentNodeId": "51" }, { "nodeId": "71", "name": "seven 2-1-1-2-1", "parentNodeId": "62" }, { "nodeId": "81", "name": "eight 2-1-1-2-1-1", "parentNodeId": "71" }, { "nodeId": "91", "name": "nine 2-1-1-2-1-1-1", "parentNodeId": "81" }, { "nodeId": "101", "name": "ten 2-1-1-2-1-1-1-1", "parentNodeId": "91" }, { "nodeId": "111", "name": "eleven 2-1-1-1-1", "parentNodeId": "101" } ] function getDescendants(entities, targetId) { // 先获取目标节点本身 const targetNode = entities.find(node => node.nodeId === targetId); if (!targetNode) return []; // 递归收集所有子孙节点 const collectChildren = (parentId) => { const children = entities.filter(node => node.parentNodeId === parentId); // 用flatMap合并当前子节点与它的所有子孙 return children.flatMap(child => [child, ...collectChildren(child.nodeId)]); }; // 返回目标节点 + 所有子孙节点的合并数组 return [targetNode, ...collectChildren(targetId)]; } const out = getDescendants(data, '32'); console.log('out', out);
修正方案二:基于原逻辑的调整
如果你想保留原函数的递归思路,可做如下修改:
function test(entities, id, result = []) { // 先将当前节点加入结果数组 const currentNode = entities.find(x => x.nodeId === id); if (currentNode) result.push(currentNode); const childrens = entities.filter(x => x.parentNodeId === id); // 递归处理每个子节点,数组是引用类型,递归中修改会同步到外层 for (const ele of childrens) { test(entities, ele.nodeId, result); } // 必须返回结果数组 return result; } const out = test(data, '32'); console.log('out', out);
验证结果
传入'32'时,两个方案都会返回包含以下节点的数组:32、41、51、61、62、71、81、91、101、111,完全符合需求。
内容的提问来源于stack exchange,提问作者spidey
相关产品推荐
相关产品推荐

