JavaScript树形数据扁平化的三种实现方法(递归/迭代/flatMap)
作者:编程随想_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" } ];
特点:
- 每个节点可能有
children
属性存放子节点。 - 层级关系不固定,可能有很多层。
- 数据访问需要递归或迭代遍历。
二、为什么要转换成普通数组?
树形结构虽然表达了层级关系,但在以下场景下并不方便:
- 全局搜索:需要遍历所有节点匹配关键字。
- 批量操作:需要一次性拿到所有节点的 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+)。
五、总结
树形结构转换为普通数组的关键点在于:
- 遍历:无论递归还是迭代,都需要访问每一个节点。
- 数据处理:在 push 到结果数组时,去掉
children
,避免冗余。 - 顺序:递归天然保证顺序,迭代需要注意入栈顺序。
在实际项目中,可以根据数据规模和浏览器兼容性选择合适的方式。
建议
在处理树形结构时,可以先封装一个通用的遍历方法,这样后续不仅能拍平数组,还可以做任意数据加工,比如筛选、映射等。
到此这篇关于JavaScript树形数据扁平化的三种实现方法(递归/迭代/flatMap)的文章就介绍到这了,更多相关JavaScript树形数据扁平化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!