导读:本期聚焦于小伙伴创作的《JavaScript扁平化嵌套JSON数组:递归与栈迭代方法详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript扁平化嵌套JSON数组:递归与栈迭代方法详解》有用,将其分享出去将是对创作者最好的鼓励。

如何用JavaScript将嵌套JSON数组扁平化

在前端开发中,我们经常会遇到结构嵌套的JSON数组数据,例如树形菜单、多级分类等场景。这类数据的嵌套层级不固定,直接处理时往往需要编写复杂的递归逻辑。将嵌套JSON数组扁平化,就是把多层嵌套的结构转换为只有一层的线性数组,方便后续的数据遍历、筛选和渲染。

嵌套JSON数组的典型结构

假设我们有如下嵌套的JSON数组,每个对象包含自身信息和子节点数组:

const nestedData = [
  {
    id: 1,
    name: '一级分类A',
    children: [
      {
        id: 2,
        name: '二级分类A1',
        children: [
          { id: 3, name: '三级分类A1-1', children: [] },
          { id: 4, name: '三级分类A1-2', children: [] }
        ]
      },
      {
        id: 5,
        name: '二级分类A2',
        children: []
      }
    ]
  },
  {
    id: 6,
    name: '一级分类B',
    children: [
      { id: 7, name: '二级分类B1', children: [] }
    ]
  }
];

扁平化的核心实现思路

扁平化的核心逻辑是遍历嵌套数组,将当前层级的对象提取出来,再递归处理其子节点(如果存在)。常见的实现方式有两种:递归遍历法和栈迭代法。

方法一:递归遍历法

递归是最直观的实现方式,逻辑清晰,适合嵌套层级不特别深的场景。步骤为:

  • 定义一个结果数组,用于存储扁平化后的数据

  • 遍历输入数组的每个元素,将当前元素(可选择性去除子节点属性)存入结果数组

  • 如果当前元素存在子节点数组且长度大于0,递归调用扁平化函数处理子节点

  • 最终返回结果数组

实现代码如下:

function flattenJsonArray(data, childrenKey = 'children') {
  const result = [];
  
  function traverse(arr) {
    arr.forEach(item => {
      // 复制当前对象,避免修改原数据
      const newItem = { ...item };
      // 如果不需要保留原数据中的children属性,可以删除
      // delete newItem[childrenKey];
      result.push(newItem);
      
      // 如果存在子节点,递归处理
      if (newItem[childrenKey] && Array.isArray(newItem[childrenKey]) && newItem[childrenKey].length > 0) {
        traverse(newItem[childrenKey]);
      }
    });
  }
  
  traverse(data);
  return result;
}

// 调用测试
const flatData = flattenJsonArray(nestedData);
console.log(flatData);

上述代码中,我们通过traverse函数递归遍历所有节点,将所有对象按顺序存入result数组。如果需要去掉扁平化后数据中的children属性,可以取消delete newItem[childrenKey];的注释。

方法二:栈迭代法

递归法在嵌套层级过深时可能出现栈溢出问题,栈迭代法通过手动维护栈结构来避免这个问题,适合处理深度嵌套的数据。步骤为:

  • 将初始数据数组放入栈中

  • 循环判断栈是否为空,不为空则取出栈顶元素

  • 将当前元素存入结果数组,将其子节点数组逆序推入栈中(保证遍历顺序和递归一致)

  • 重复上述步骤直到栈为空

实现代码如下:

function flattenJsonArrayByStack(data, childrenKey = 'children') {
  const result = [];
  // 初始化栈,将初始数据放入
  const stack = [...data];
  
  while (stack.length > 0) {
    const current = stack.pop();
    // 复制当前对象,避免修改原数据
    const newItem = { ...current };
    result.push(newItem);
    
    // 如果存在子节点,逆序推入栈中,保证遍历顺序和递归一致
    if (newItem[childrenKey] && Array.isArray(newItem[childrenKey]) && newItem[childrenKey].length > 0) {
      // 逆序推入,因为栈是后进先出
      stack.push(...newItem[childrenKey].reverse());
    }
  }
  
  return result;
}

// 调用测试
const flatDataByStack = flattenJsonArrayByStack(nestedData);
console.log(flatDataByStack);

两种方法的对比

可以通过以下表格对比两种实现方案的特点:

对比维度递归遍历法栈迭代法
代码可读性逻辑直观,容易理解需要理解栈的工作原理,可读性稍弱
嵌套深度限制受调用栈深度限制,过深可能栈溢出无调用栈限制,适合深度嵌套数据
遍历顺序默认深度优先遍历可调整栈的入栈顺序控制遍历顺序

实际场景中的扩展处理

在实际业务中,我们可能还需要给扁平化后的数据添加层级标识,方便后续区分不同层级的数据。例如给每个节点添加level字段表示其所在层级:

function flattenJsonArrayWithLevel(data, childrenKey = 'children', currentLevel = 1) {
  const result = [];
  
  function traverse(arr, level) {
    arr.forEach(item => {
      const newItem = { ...item, level };
      result.push(newItem);
      
      if (newItem[childrenKey] && Array.isArray(newItem[childrenKey]) && newItem[childrenKey].length > 0) {
        traverse(newItem[childrenKey], level + 1);
      }
    });
  }
  
  traverse(data, currentLevel);
  return result;
}

// 调用测试,一级节点level为1,二级为2,以此类推
const flatDataWithLevel = flattenJsonArrayWithLevel(nestedData);
console.log(flatDataWithLevel);

通过这种方式,扁平化后的数据不仅保留了原有信息,还增加了层级标识,更适合用于树形结构的展开折叠、缩进渲染等场景。

注意事项

在处理嵌套JSON数组时,需要注意以下几点:

  • 避免直接修改原数据,建议通过展开运算符...或者Object.assign复制对象后再处理

  • 如果子节点属性名不是默认的children,可以通过参数传入自定义的属性名,提高函数通用性

  • 如果数据中存在循环引用(例如子节点引用父节点),需要额外添加已访问对象的判断,避免死循环

通过上述方法,我们可以快速实现嵌套JSON数组的扁平化,根据实际的嵌套深度和业务需求选择合适的实现方案即可。

JavaScript JSON扁平化 递归算法 栈迭代 前端开发

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。