递归函数处理深层嵌套数组时出现Maximum Call Stack Size Exceeded错误
解决深度嵌套数组递归求和的栈溢出问题
你的代码触发Maximum Call Stack Size Exceeded错误的核心原因是:JavaScript引擎的调用栈有固定上限(多数浏览器约8000-10000层),而你生成的嵌套数组有10000层,递归调用sumArray的次数刚好超过了这个上限,导致栈溢出。
下面提供三种可靠的解决方案:
方案1:迭代法(最稳妥,无栈限制)
手动维护遍历栈,用循环替代递归,完全避开调用栈的限制:
const ElementsCount = 10000; const createDeeplyNestedArray = (ElementsCount) => { let retval = [1]; for (let i = 0; i < ElementsCount - 1; i++) { retval = [1, retval]; } return retval; }; const deeplyNestedArray = createDeeplyNestedArray(ElementsCount); function sumArrayIterative(arr) { let sum = 0; const stack = [arr]; while (stack.length > 0) { const current = stack.pop(); for (const entry of current) { if (typeof entry === 'number') { sum += entry; } else { stack.push(entry); } } } return sum; } const res = sumArrayIterative(deeplyNestedArray); console.log(res); // 输出10000
方案2:蹦床函数(同步转循环)
通过蹦床函数将递归调用拆解为循环执行,既保留递归的写法逻辑,又避免栈溢出:
const ElementsCount = 10000; const createDeeplyNestedArray = (ElementsCount) => { let retval = [1]; for (let i = 0; i < ElementsCount - 1; i++) { retval = [1, retval]; } return retval; }; const deeplyNestedArray = createDeeplyNestedArray(ElementsCount); // 蹦床函数:循环执行返回的函数,直到得到最终结果 function trampoline(fn) { while (typeof fn === 'function') { fn = fn(); } return fn; } function sumArrayTrampoline(arr) { function helper(currentArr, currentSum) { let sum = currentSum; for (const entry of currentArr) { if (typeof entry === 'number') { sum += entry; } else { // 返回待执行的函数,而非直接递归调用 return () => helper(entry, sum); } } return sum; } return trampoline(() => helper(arr, 0)); } const res = sumArrayTrampoline(deeplyNestedArray); console.log(res); // 输出10000
方案3:异步递归(基于setTimeout)
利用setTimeout将每次递归调用放入宏任务队列,绕过调用栈限制,但结果为异步,需用Promise处理:
const ElementsCount = 10000; const createDeeplyNestedArray = (ElementsCount) => { let retval = [1]; for (let i = 0; i < ElementsCount - 1; i++) { retval = [1, retval]; } return retval; }; const deeplyNestedArray = createDeeplyNestedArray(ElementsCount); function sumArrayAsync(arr) { return new Promise((resolve) => { let sum = 0; function process(currentArr) { for (const entry of currentArr) { if (typeof entry === 'number') { sum += entry; } else { // 将递归调用推迟到下一个宏任务 setTimeout(() => process(entry), 0); return; } } resolve(sum); } process(arr); }); } sumArrayAsync(deeplyNestedArray).then(res => console.log(res)); // 输出10000
内容的提问来源于stack exchange,提问作者tmndungu
相关产品推荐
相关产品推荐

