函数尾调用优化

尾调用

在编码过程中,经常涉及到函数调用函数,例如:

javascript 复制代码
function a() {
  b();
}

function b() {}

我们每次调用函数,都会在在内存中记录一个"调用帧"又成为"栈帧空间"

在上述例子中,调用a()函数,会在内存中记录一个调用栈,然后继续调用b()函数,此时在内存中又会记录一个调用帧,等到b()函数运行结束,调用帧a、b的内存才会释放。

我们可以利用"尾调用"来释放调用帧内存

javascript 复制代码
function a() {
  return b();
}

function b() {}

上述代码中,在函数的最后一步调用了b()函数,外层函数内存直接被释放,确认代之的是b()函数内存被创建,从复杂度来看,普通调用复杂度O(n),尾调用复杂度O(1)

尾调用并不是函数中的最后一行,而是最后一步,在下面的例子中,也可以实现尾调用

javascript 复制代码
function a(n) {
  if(n === 5){
    return b();  // 尾调用
  }
  return c(); // 尾调用
}

尾递归

递归函数就是函数调用自身,正常的递归函数会进行深层调用,每次调用函数都会创建内存,也就是上面所说的调用帧,直到递归函数执行完毕,内存才会被释放,如果递归函数层级过深,记录栈帧过多,会导致栈溢出错误。

我们可以利用尾调用来优化并释放内存,下面是一个尾递归函数

javascript 复制代码
/* 尾递归 */
function tailRecur(n, res) {
    // 终止条件
    if (n === 0) return res;
    // 尾递归调用
    return tailRecur(n - 1, res + n);
}
相关推荐
linux_cfan1 小时前
17 · 引擎适配器全景:HLS/DASH/Vimeo/Mux/Cast
前端·javascript·音视频
计算机魔术师2 小时前
烧掉2780亿美元还不够?OpenAI的资本豪赌让人头皮发麻
前端
IT_陈寒2 小时前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
神秘的猪头3 小时前
React 脱围机制(二):重新理解 useEffect——它不是生命周期,而是同步外部系统
react.js
卡布鲁3 小时前
React useMemo 与 useCallback 完全指南:原理、场景与避坑
前端·react.js
碳基修炼3 小时前
排查记:本地 devServer 是 http,浏览器却把 302 重定向升级成了 https
前端·http
步行cgn3 小时前
Spring p 命名空间注入详解
java·前端·spring
何何____3 小时前
Vue 生命周期详解
前端·javascript
江米小枣tonylua3 小时前
TypeScript 全面の拥抱 !Prisma 8 + Electron 升级实战
前端
闪耀之光M784 小时前
npm命令解析
前端