递归函数中的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
相关产品推荐
相关产品推荐

