JavaScript树形数据扁平化的三种实现方法(递归/迭代/flatMap)

 更新时间:2025年08月18日 09:57:31   作者:编程随想_Code  
树形数据结构在前端应用中被广泛用于表示层级关系的数据,如菜单、部门结构、文件目录等,扁平化操作通常是指将具有层级关系的树形数据转换为单一维度的数据结构,即数组,本文给大家介绍了JavaScript树形数据扁平化的三种实现方法,需要的朋友可以参考下

在前端开发中,我们经常会遇到 树形结构(Tree Data Structure) 的数据,比如:

  • 菜单列表(菜单 → 子菜单 → 孙菜单)
  • 部门组织架构(公司 → 部门 → 小组 → 员工)
  • 树状分类(分类 → 子分类 → 子子分类)

而有时候,我们需要将树形数据拍平成一维数组,方便做搜索、统计、映射等操作。

一、树形结构的特点

一个典型的树形结构数据可能是这样的:

const treeData = [
  {
    id: 1,
    name: "A",
    children: [
      {
        id: 2,
        name: "A-1",
        children: [
          { id: 3, name: "A-1-1" },
          { id: 4, name: "A-1-2" }
        ]
      },
      {
        id: 5,
        name: "A-2"
      }
    ]
  },
  {
    id: 6,
    name: "B"
  }
];

特点:

  1. 每个节点可能有 children 属性存放子节点。
  2. 层级关系不固定,可能有很多层。
  3. 数据访问需要递归或迭代遍历。

二、为什么要转换成普通数组?

树形结构虽然表达了层级关系,但在以下场景下并不方便:

  • 全局搜索:需要遍历所有节点匹配关键字。
  • 批量操作:需要一次性拿到所有节点的 ID 或名称。
  • 统计:统计节点数量、节点类型等。

将树形数据拍平成数组后,数据会变成这样:

[
  { id: 1, name: "A" },
  { id: 2, name: "A-1" },
  { id: 3, name: "A-1-1" },
  { id: 4, name: "A-1-2" },
  { id: 5, name: "A-2" },
  { id: 6, name: "B" }
]

这样处理起来就非常方便。

三、实现方法

方法一:递归实现

递归是处理树形结构的经典方式。

function treeToArray(tree) {
  let result = [];

  function traverse(nodeList) {
    for (const node of nodeList) {
      // 拷贝当前节点(防止修改原数据)
      const { children, ...rest } = node;
      result.push(rest);

      // 如果有子节点,递归处理
      if (children && children.length) {
        traverse(children);
      }
    }
  }

  traverse(tree);
  return result;
}

const flatArray = treeToArray(treeData);
console.log(flatArray);

运行结果:

[
  { id: 1, name: 'A' },
  { id: 2, name: 'A-1' },
  { id: 3, name: 'A-1-1' },
  { id: 4, name: 'A-1-2' },
  { id: 5, name: 'A-2' },
  { id: 6, name: 'B' }
]

方法二:迭代(栈)实现

如果不想用递归,可以用栈来实现。

function treeToArrayIterative(tree) {
  let result = [];
  let stack = [...tree]; // 先把根节点放进栈

  while (stack.length) {
    const node = stack.pop();
    const { children, ...rest } = node;
    result.push(rest);

    // 注意:这里用栈,所以先放子节点才能保证顺序
    if (children && children.length) {
      stack.push(...children);
    }
  }

  return result;
}

const flatArray2 = treeToArrayIterative(treeData);
console.log(flatArray2);

方法三:使用 Array.flatMap(ES2019+)

如果层级不深,可以用 flatMap + 递归的方式更简洁:

function treeToArrayFlatMap(tree) {
  return tree.flatMap(({ children, ...rest }) =>
    children ? [rest, ...treeToArrayFlatMap(children)] : [rest]
  );
}

console.log(treeToArrayFlatMap(treeData));

四、性能对比

  • 递归:代码简洁、可读性好,适合绝大多数场景。
  • 迭代:避免递归栈溢出,适合极深层级的树。
  • flatMap:语法简洁,但浏览器兼容性略差(需 ES2019+)。

五、总结

树形结构转换为普通数组的关键点在于:

  1. 遍历:无论递归还是迭代,都需要访问每一个节点。
  2. 数据处理:在 push 到结果数组时,去掉 children,避免冗余。
  3. 顺序:递归天然保证顺序,迭代需要注意入栈顺序。

在实际项目中,可以根据数据规模和浏览器兼容性选择合适的方式。

建议

在处理树形结构时,可以先封装一个通用的遍历方法,这样后续不仅能拍平数组,还可以做任意数据加工,比如筛选、映射等。

到此这篇关于JavaScript树形数据扁平化的三种实现方法(递归/迭代/flatMap)的文章就介绍到这了,更多相关JavaScript树形数据扁平化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript forEach方法用法示例实战

    JavaScript forEach方法用法示例实战

    本文将详细介绍forEach方法的基本概念、用法、常见的应用场景、与其他遍历方法的对比,并提供实战示例,帮助您全面掌握这一强大的工具,感兴趣的朋友跟随小编一起看看吧
    2025-06-06
  • JavaScript中不可忽略的Symbol的盘点

    JavaScript中不可忽略的Symbol的盘点

    Symbol类型的出现,为每个属性赋予了独一无二的标识符,无论项目多么复杂,Symbol都能确保属性键的绝对唯一性,下面我们就来看看JavaScript中那些不可忽略的Symbol吧
    2024-12-12
  • JavaScript中的scrollTop详解(滚动到顶部)

    JavaScript中的scrollTop详解(滚动到顶部)

    scrollTop是JavaScript中一个非常有用且重要的方法,它用于获取或设置元素的垂直滚动条位置,这篇文章主要给大家介绍了关于JavaScript中scrollTop详解(滚动到顶部)的相关资料,需要的朋友可以参考下
    2023-12-12
  • JavaScript封装LINQ查询方法实战

    JavaScript封装LINQ查询方法实战

    本文主要介绍了通过js-linq库在JavaScript中实现类似.NET LINQ的查询功能,封装Where、Select、OrderBy等方法,提升数组和可迭代对象的数据处理效率与代码可读性
    2025-09-09
  • javascript设计模式--策略模式之输入验证

    javascript设计模式--策略模式之输入验证

    策略模式中的策略就是一种算法或者业务规则,将这些策略作为函数进行封装,并向外提供统一的调用执行,本文给大家介绍javascript设计模式--策略模式之输入验证,需要的朋友参考下
    2015-11-11
  • JavaScript仿聊天室聊天记录

    JavaScript仿聊天室聊天记录

    这篇文章主要为大家详细介绍了JavaScript仿聊天室聊天记录实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • 微信小程序之数据缓存的实例详解

    微信小程序之数据缓存的实例详解

    这篇文章主要介绍了微信小程序之数据缓存的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这部分内容,需要的朋友可以参考下
    2017-09-09
  • JavaScript实现清除首尾空白字符再进行空白匹配

    JavaScript实现清除首尾空白字符再进行空白匹配

    这篇文章主要为大家详细介绍了JavaScript实现清除首尾空白字符再进行空白匹配的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2025-12-12
  • 详解bootstrap导航栏.nav与.navbar区别

    详解bootstrap导航栏.nav与.navbar区别

    本篇文章主要介绍了详解bootstrap导航栏.nav与.navbar区别,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • js使用setTimeout实现定时炸弹的方法

    js使用setTimeout实现定时炸弹的方法

    这篇文章主要介绍了js使用setTimeout实现定时炸弹的方法,涉及javascript中setTimeout方法的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04

最新评论