如何追踪JavaScript递归斐波那契函数并统计递归调用次数
追踪递归斐波那契函数的调用次数
嘿,我完全理解你想追踪这个递归斐波那契函数调用次数的需求——虽然递归求斐波那契确实效率不高,但用来学习递归调用流程还是挺合适的。你提到的15次调用应该是输入num=5时的情况对吧?咱们来一步步实现这个计数器,有几种不同的方案可以选:
方案1:全局计数器(简单直观)
这是最容易上手的方式,定义一个全局变量统计调用次数,每次进入fibonacci函数就把计数器加1:
// 初始化全局计数器 let callCount = 0; function fibonacci(num) { callCount++; // 每次调用函数就计数+1 // 可选:打印每次调用的参数,清晰看到执行步骤 console.log(`正在执行 fibonacci(${num})`); if (num < 2) { return num; } return fibonacci(num - 1) + fibonacci(num - 2); } // 测试求fib(5),预期总调用次数15次 fibonacci(5); console.log(`总调用次数:${callCount}`);
注意点:
- 如果要多次测试,记得每次调用前重置
callCount = 0,不然计数会累加 - 全局变量可能会被其他代码意外修改,适合简单测试场景
方案2:闭包封装计数器(更优雅,无全局污染)
如果不想用全局变量,可以用闭包把计数器封装起来,既保留计数功能,又不会污染全局作用域:
function createTrackedFibonacci() { // 闭包内的计数器,外部无法直接修改 let callCount = 0; function fibonacci(num) { callCount++; console.log(`调用 fibonacci(${num})`); if (num < 2) { return num; } return fibonacci(num - 1) + fibonacci(num - 2); } // 返回操作接口,方便获取计数和重置 return { fibonacci, getCallCount: () => callCount, resetCount: () => { callCount = 0; } }; } // 使用方式 const trackedFib = createTrackedFibonacci(); trackedFib.fibonacci(5); console.log(`总调用次数:${trackedFib.getCallCount()}`); // 输出15 // 重置后可以再次测试 trackedFib.resetCount(); trackedFib.fibonacci(3); console.log(`总调用次数:${trackedFib.getCallCount()}`); // 输出5
这个方案更健壮,适合需要多次测试或者在复杂项目中使用的场景。
方案3:参数传递计数器(无状态调用)
如果你不想依赖外部变量,可以把计数器作为可选参数传递给递归函数,每次递归时更新计数:
function fibonacci(num, callCount = 0) { callCount++; console.log(`调用 fibonacci(${num}),当前累计调用:${callCount}`); if (num < 2) { // 返回结果和当前计数 return { result: num, count: callCount }; } // 递归调用左分支,获取左分支的结果和累计计数 const leftBranch = fibonacci(num - 1, callCount); // 把左分支的计数传递给右分支,继续累计 const rightBranch = fibonacci(num - 2, leftBranch.count); // 返回最终结果和总计数 return { result: leftBranch.result + rightBranch.result, count: rightBranch.count }; } // 测试 const { result, count } = fibonacci(5); console.log(`fib(5)的结果:${result}`); console.log(`总调用次数:${count}`); // 输出15
这个方案的好处是每次调用都是独立的,不需要额外重置操作,但需要修改函数的返回值来同时携带结果和计数。
为什么你之前可能没成功?
大概率是计数器的位置不对——比如你可能把计数逻辑放在了if(num<2)的判断之后,这样base case(num=0或num=1)的调用就没被统计进去,导致计数比实际少。一定要把callCount++放在函数的最开头,确保每一次函数调用都被计数。
内容的提问来源于stack exchange,提问作者Joji
相关产品推荐
相关产品推荐

