函数尾调用优化

尾调用

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

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);
}
相关推荐
超哥--1 小时前
B站视频内容智能分析系统(九):React 前端与管理面板
前端·react.js·前端框架
Cutecat_4 小时前
视频字幕处理工具横向:提取模式 vs 编辑模式,该如何选择
android·前端·ios·语音识别
dsyyyyy11014 小时前
JavaScript变量
开发语言·javascript·ecmascript
qq_422152574 小时前
PDF 加水印工具怎么选?2026 年文档版权保护方案对比
前端·pdf·github
kyriewen5 小时前
手写 Promise.all、race、any:不到 30 行代码,解决并发异步的所有姿势
前端·javascript·面试
brucelee1865 小时前
OpenClaw 浏览器控制(Chrome MCP)完整教程
前端·chrome
ct9786 小时前
React 状态管理方案深度对比
开发语言·前端·react
胡志辉的博客6 小时前
深入浅出理解浏览器事件循环:从一道输出题讲到 Chrome 源码
前端·javascript·chrome·chromium·event loop
代码不加糖6 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
懂懂tty6 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js