You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript递归函数无法返回指定节点所有子孙节点问题

解决递归获取子孙节点无法正确返回结果的问题

你的递归函数能生成所需的节点列表,但因为未正确处理递归返回值、缺少最终返回语句,且遗漏了目标节点本身的收集,导致无法输出正确结果。以下是问题分析和修正方案:

问题根源

  1. 原函数未将传入id对应的目标节点加入结果列表,只收集了它的子节点;
  2. 递归调用时未处理返回值,且最后没有返回结果数组,导致外层调用得到undefined;
  3. 使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:25:10