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

递归函数中的while循环执行多次时运行失败

问题分析与修复方案

咱们先来拆解你遇到的问题:当while循环条件设为data.c <7(多次执行)时代码“失败”,本质是数组引用被修改导致死循环,再加上return语句的逻辑冗余,才引发了异常。

核心问题1:数组引用的副作用

在while分支里,你写了var brNodes = first.b[0].actions——这里brNodes是直接引用了原数组的内存地址,不是创建副本。第一次调用recurse(data, brNodes)时,里面的nodes.shift()会把brNodes数组的元素逐个移除,等第二次循环的时候,brNodes已经是空数组了!

这就导致后续的while循环里,调用recurse根本不会执行任何action,data.c的值不再增长,data.c <7的条件永远成立,代码直接陷入死循环,看起来就像是“失败”了。

核心问题2:return语句的冗余console.log

你的return语句里写了console.log(recurse(data, nodes), 200),这会先执行递归调用,然后把递归的返回值传给console.log,但console.log本身返回的是undefined,这会覆盖递归原本应该返回的"Completed"或者递归结果,导致逻辑混乱。


修复后的代码

我把这两个问题都修正了,你可以直接运行试试:

var data = { a: "abc", c: 0 }
function recurse(data, nodes) {
  // 每次调用都复制传入的数组,避免修改原数组导致后续循环失效
  const currentNodes = [...nodes];
  const first = currentNodes.shift();
  if (!first) { // 处理空数组的边界情况,防止报错
    return "Completed";
  }
  console.log("first-"+first.id, first.t);
  if (first.t == "action") {
    data.c = data.c + 1;
    console.log("exec action", data.c);
  } else {
    switch (first.t) {
      case "if_else":
        // 复制分支的actions数组,避免修改原数据
        recurse(data, [...first.b[0].actions]);
        break
      case "while":
        const brNodes = first.b[0].actions;
        while (data.c < 7) {
          // 每次循环都传数组副本,保证每次都能完整执行分支里的action
          recurse(data, [...brNodes]);
        }
        break
      default:
        break
    }
  }
  // 直接返回递归调用的结果,不要用console.log包裹,保证返回值正确
  return currentNodes.length > 0 ? recurse(data, currentNodes) : "Completed"
}
var actions = [
  {id:1, t:"action", b:null},
  {id:2, t:"action", b:null},
  {id:3, t:"if_else", b:[{id:31, t:"branch", actions:[{id:311, t:"action", b:null}, {id:312, t:"action", b:null}]},{id:32, t:"branch", actions:[{id:321, t:"action", b:null}]}]},
  {id:4, t:"action", b: null},
  {id:5, t:"while", b:[{id:500, t:"branch", actions:[{id:511, t:"action", b:null}]}]},
  {id:6, t:"action", b:null}
]
console.log(recurse(data, actions), 100)

关键修复点说明

  • 每次调用recurse时,都用[...nodes]复制传入的数组,这样shift()只会修改副本,不会影响原数组或者后续循环要用到的数组。
  • 移除了return语句里多余的console.log,保证递归的返回值正确传递,不会被undefined覆盖。
  • 增加了空数组的边界判断,避免first为undefined时出现报错。

现在你把while条件设为data.c <7,代码会正常执行到data.c等于7,然后退出while循环,继续执行后续的action。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:32:42