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

如何遍历JavaScript对象数组构建树形层级结构?

嘿,我来帮你搞定把JavaScript对象数组转成树形层级结构的问题!其实这个需求的核心思路很清晰,咱们一步步来实现:

实现思路与步骤

首先得明确你的原始数据结构——一般来说,每个对象都会有唯一标识(比如id)和父节点标识(比如parentId),根节点的parentId可以设为null或者特定值(比如0)。我先假设你的输入数据长这样:

const rawData = [
  { id: 1, name: 'Root Parent 01', parentId: null },
  { id: 2, name: 'Root Parent 02', parentId: null },
  { id: 3, name: 'Root Parent 03', parentId: null },
  { id: 4, name: 'Child 01', parentId: 3 },
  { id: 5, name: 'Child 02', parentId: 3 },
  { id: 6, name: 'Child 03', parentId: 3 },
  { id: 7, name: 'Root Parent 04', parentId: null },
  { id: 8, name: 'Child 04', parentId: 7 },
  { id: 9, name: 'Child 05', parentId: 7 },
  { id: 10, name: 'Child 06', parentId: 7 },
  { id: 11, name: 'Child 07', parentId: 7 },
  { id: 12, name: 'Child 08', parentId: 7 },
  { id: 13, name: 'Child 09', parentId: 7 },
  { id: 14, name: 'Child 10', parentId: 7 },
  { id: 15, name: 'Child 11', parentId: 7 },
  { id: 16, name: 'Root Parent 05', parentId: null },
  { id: 17, name: 'Child 12', parentId: 16 },
  { id: 18, name: 'Child 13', parentId: 16 },
  { id: 19, name: 'Child 14', parentId: 16 },
  { id: 20, name: 'Child 15', parentId: 16 },
  { id: 21, name: 'Child 16', parentId: 16 },
  { id: 22, name: 'Child 17', parentId: 16 },
  { id: 23, name: 'Child 19', parentId: 16 },
  { id: 24, name: 'Child 18', parentId: 23 }
];

1. 构建节点映射表

首先我们需要一个快速查找节点的映射表(用Map或者普通对象都行),同时给每个节点初始化一个children数组,用来存放子节点:

const nodeMap = new Map();

// 遍历原始数据,把每个节点存入映射表,并初始化children
rawData.forEach(item => {
  nodeMap.set(item.id, { ...item, children: [] });
});

这个映射表的好处是能让我们以O(1)的时间复杂度快速定位任意节点,整个构建过程的时间复杂度是O(n),效率很高

2. 组装树形结构

接下来遍历所有节点,把非根节点挂载到对应的父节点的children数组里,根节点直接加入顶层树形数组:

const tree = [];

rawData.forEach(item => {
  const currentNode = nodeMap.get(item.id);
  
  if (item.parentId === null) {
    // 根节点直接加入树形结构顶层
    tree.push(currentNode);
  } else {
    // 找到父节点,将当前节点加入父节点的children
    const parentNode = nodeMap.get(item.parentId);
    if (parentNode) { // 做个容错,避免父节点不存在的情况
      parentNode.children.push(currentNode);
    }
  }
});

3. 验证树形结构(打印输出)

为了确认结果符合你的预期,我们可以写一个递归函数来打印树形结构:

function printTree(nodes, indent = '') {
  nodes.forEach(node => {
    console.log(`${indent}${node.name}`);
    // 如果有子节点,递归打印,增加缩进
    if (node.children.length > 0) {
      printTree(node.children, indent + '---');
    }
  });
}

// 调用打印函数
printTree(tree);

运行这段代码后,控制台输出就会和你预期的结构完全一致:

Root Parent 01
Root Parent 02
Root Parent 03
---Child 01
---Child 02
---Child 03
Root Parent 04
---Child 04
---Child 05
---Child 06
---Child 07
---Child 08
---Child 09
---Child 10
---Child 11
Root Parent 05
---Child 12
---Child 13
---Child 14
---Child 15
---Child 16
---Child 17
---Child 19
------Child 18

注意事项

  • 如果你的根节点标识不是null(比如用0或者''),记得修改判断条件item.parentId === null为对应的标识;
  • 如果原始数据中存在父节点不存在的情况,上面的代码会自动跳过这些节点,你也可以根据需求添加错误提示;
  • 如果你不想修改原始对象,记得用扩展运算符{ ...item }创建副本,避免污染原数据。

内容的提问来源于stack exchange,提问作者Cody Tolene

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:34:41