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

JavaScript如何将扁平分类数组构建为向上嵌套的深度对象

问题原因

你的代码返回根节点的核心原因是递归返回逻辑写反了:

  • 你当前的递归逻辑是从起始节点向上遍历到根节点,每次都返回父节点的递归结果,最终递归终止时会直接把根节点作为最终结果返回,完全丢弃了最开始的id=4的RAM节点引用
  • 另外你的实现直接修改了原始categories数组里的对象引用,会污染原始数据,产生意料之外的副作用
正确实现方案

推荐用不修改原始数据的写法,同时提前构建id映射表提升查询效率,不需要每次遍历数组找父节点:

const categories = [
  {id: 1, name: "Main", parent: null},
  {id: 2, name: "Computers", parent: 1},
  {id: 3, name: "Components", parent: 2},
  {id: 4, name: "RAM", parent: 3}
];

// 构建id到节点的映射,避免重复find遍历
const categoryMap = new Map(categories.map(item => [item.id, item]));

/**
 * 从指定id的节点开始,向上构建嵌套父级结构
 * @param {number} nodeId 起始节点id
 * @returns 挂载完整父级链的节点对象
 */
const buildNestedChain = (nodeId) => {
  const originNode = categoryMap.get(nodeId);
  // 浅拷贝节点,避免修改原始数据
  const currentNode = { ...originNode };

  // 到达根节点,parent设为null后直接返回
  if (originNode.parent === null) {
    currentNode.parent = null;
    return currentNode;
  }

  // 递归构建父级的嵌套链,挂载到当前节点的parent属性上
  currentNode.parent = buildNestedChain(originNode.parent);
  return currentNode;
};

// 从id=4的RAM节点开始构建
const result = buildNestedChain(4);
console.log(result);

运行上述代码就能得到你期望的嵌套结构。

快速修复原有代码的方式

如果你不想大幅改动原有逻辑,只需要调整返回逻辑即可,注意这种方式会修改原始数组数据:

const recursiveBuild = (node) => {
  if (node.parent === null) {
    return;
  }
  const parent = categories.find((cat) => cat.id === node.parent);
  node.parent = parent;
  recursiveBuild(node.parent);
};

const item4 = categories.find((cat) => cat.id === 4);
recursiveBuild(item4);
// 递归过程已经直接修改了item4的引用,此时item4就是目标结构
console.log(item4);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:54:42