JavaScript数组扁平化有6种方法:flat(Infinity)、递归、reduce+concat、JSON.stringify+replace+split、正则改良版(JSON.parse)、扩展运算符+some,核心是将多维数组转为一维。

JavaScript 中并没有所谓“JSON.stringify 的反向替换机制”。JSON.stringify 本身不具备“反向替换”或“解析后处理”的能力,它只是单向序列化:把 JavaScript 对象/数组转为字符串。你提到的“动态重组嵌套菜单为扁平路由”,实际是前端路由配置(如 Vue Router、React Router)中常见的数据结构转换问题,核心在于**递归遍历 + 路径拼接 + 路由元信息提取**,而非依赖 JSON.stringify 的任何“反向”特性。
理解真实需求:嵌套菜单 → 扁平路由数组
典型场景是后端返回一个树形菜单结构(含 children),而前端路由系统(如 Vue Router 的 createRouter({ routes: [...] }))需要的是扁平的一维路由配置数组,每项包含 path、component、name、meta 等字段,且子路由的 path 需继承父级路径(如 /system → /system/user)。
正确做法:用递归函数扁平化并构造路由对象
不依赖 JSON.stringify,而是直接操作原始数据结构。关键点:
- 递归遍历菜单节点,每层累积 path(如
base + '/' + item.path) - 跳过无 component 或无 path 的节点(菜单项 ≠ 路由项)
- 将 menu item 映射为 route config,保留 icon、title、permission 等到 meta 字段
- 可选:对 children 进行排序、过滤权限、标记 layout 类型(如 Layout、BlankLayout)
示例代码(通用 JS,适配 Vue Router / React Router)
假设后端返回菜单数据如下:
立即学习“Java免费学习笔记(深入)”;
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
{ id: 1, title: '系统管理', path: '/system', children: [
{ id: 2, title: '用户管理', path: 'user', component: './views/system/User.vue' },
{ id: 3, title: '角色管理', path: 'role', component: './views/system/Role.vue' }
] },
{ id: 4, title: '仪表盘', path: '/dashboard', component: './views/Dashboard.vue' }
];
扁平化函数:
function flattenMenuToRoutes(menuList, basePath = '', parentMeta = {}) {
const routes = [];
for (const item of menuList) {
// 构建完整 path
const fullPath = basePath + (item.path.startsWith('/') ? item.path : `/${item.path}`);
// 若有 component,视为可访问路由
if (item.component) {
routes.push({
path: fullPath,
name: item.name || item.title?.replace(/\s/g, ''),
component: () => import(item.component),
meta: {
title: item.title,
icon: item.icon,
permission: item.permission,
...parentMeta
}
});
}
// 递归处理子菜单(子路由作为嵌套路由时,常需额外逻辑;若纯扁平则继续 push)
if (Array.isArray(item.children) && item.children.length > 0) {
const childRoutes = flattenMenuToRoutes(
item.children,
fullPath, // 子项继承父 path
{ ...parentMeta, ...(item.meta || {}) }
);
routes.push(...childRoutes);
}
}
return routes;
}
// 使用
const flatRoutes = flattenMenuToRoutes(menuData);
// → [{ path: '/system', ... }, { path: '/system/user', ... }, ...]
为什么不用 JSON.stringify?
有人尝试用 JSON.stringify(obj, (k, v) => {...}) 的 replacer 函数做“边序列化边修改”,但这属于 hack 行为:
- replacer 只能修改值,不能新增字段、不能控制结构层级、无法获取父级上下文
- 序列化结果是字符串,还需再
JSON.parse,性能差且易出错(如函数、undefined、Date 会丢失) - 无法自然处理动态 import()、组件引用、路由守卫等运行时逻辑
真正健壮的做法永远是:**保持数据原生结构,用语义清晰的递归或 reduce 实现转换**。


















