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

JavaScript递归遍历嵌套数组搜索元素时代码异常如何修复

问题说明

实现无限嵌套结构的搜索功能:输入搜索关键词,返回所有层级中title字段包含关键词的元素组成的数组。最初采用递归逻辑编写代码,但运行结果不符合预期,无法定位错误。
测试数据与原有问题代码如下:

const newList = [
  {
      role: "role111",
      title: "title1",

  },
  {
      role: "role222",
      title: "title2",
  },
  {
      role: "role333",
      title: "title3",
  },
  {
      role: "role444",
      title: "title4",
      items: [{
          role: "role555",
          title: "title5",
      }, {
          role: "role666",
          title: "title6",
      }, {
          role: "role777",
          title: "title7",
          items: [{
              role: "role888",
              title: "title888",
          },{
              role: "role8888",
              title: "title8888",
          },]
      },]
  },
  {
      role: "role999",
      title: "title999",
  },
];

const text = "role888";


const testFunction = (
  list,
  text,
  emptyArray
) => {
  let arrayForRender = emptyArray;

  return list?.filter((item) => {
      if (item.title.toLowerCase().includes(text.toLowerCase())) {
          arrayForRender = [...arrayForRender, item];
          return arrayForRender;
      }
      if (item.items && item.items?.length > 0) {
          testFunction(item.items, text, arrayForRender);
      }
  });
};

console.log(testFunction(newList, text, []));

附言:非常抱歉,我最初的问题表述有误,原问题已不再适用。但仍然感谢所有已经给出建议、以及即将指导我正确掌握递归用法的各位。

错误点梳理
  • 对Array.filter的用法理解错误:filter的回调函数需要返回布尔值,用来判定当前遍历项是否要保留在返回的新数组中。原代码在匹配时返回数组对象(属于真值),会导致所有遍历到的顶层元素不管是否匹配都被保留,最终返回的是顶层数组的错误子集,而非收集到的所有匹配项。
  • 递归调用的返回值未被接收:处理子节点items时调用了递归函数,但没有接收递归返回的结果,深层节点匹配到的内容完全没有被累计到最终结果中。
  • 结果累计逻辑失效:原代码通过参数传入初始空数组存储结果,但每次匹配时用展开运算符创建新数组赋值给局部变量arrayForRender,子递归中创建的新数组无法同步到父级作用域,深层匹配的元素不会被存入最终的结果数组。
修复方案

放弃用filter做跨层级结果收集,改用遍历+递归结果合并的逻辑,每层递归维护自己的结果数组,将子节点递归得到的匹配结果直接合并到当前层结果中即可:

const testFunction = (list, text) => {
  const result = [];
  // 非数组场景直接返回空结果兜底
  if (!Array.isArray(list)) return result;
  const keyword = text.toLowerCase();

  for (const item of list) {
    // 当前节点匹配则加入结果
    if (typeof item.title === 'string' && item.title.toLowerCase().includes(keyword)) {
      result.push(item);
    }
    // 存在子节点则递归搜索,将子节点匹配结果合并到当前结果
    if (Array.isArray(item.items) && item.items.length) {
      result.push(...testFunction(item.items, text));
    }
  }

  return result;
};

// 测试
console.log(testFunction(newList, text));
// 输出:[{role: 'role888', title: 'title888'}, {role: 'role8888', title: 'title8888'}]
逻辑说明
  • 不需要额外传入初始空数组参数,避免参数传递带来的作用域同步问题。
  • 增加了类型判断兜底,避免字段不存在、值类型不符合预期时抛出运行时错误。
  • 递归逻辑清晰:当前层匹配项直接存入结果,子层所有匹配项通过递归获取后合并,不管嵌套多少层都能正确收集所有匹配元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:30:47