尾调用

尾调用就是指在调用的函数中,函数的最后一步是调用另一个函数。

function f(x){
  return g(x);
}

像上面的例子中,f函数最后调用的g函数,这就是尾调用。

最后一步一定要是return一个函数而且仅能是一个函数,不能是一个表达式,也不能是一个对象。

为什么会有尾调用这个东西,尾调用有什么好处呢?其实在函数的调用过程中,会在内存中形成一个调用记录,称为调用帧,在函数的层层调用时,调用帧会一层层的叠加,这样就形成了调用栈,只有上一层的函数调用完成才会返回上一层,继续执行。

如果进行尾调用优化,在最后一步调用函数后,改函数就可以销毁,相当于直接调用了最终函数

function f() {
  let m = 1;
  let n = 2;
  return g(m + n);
}
f();

// 等同于
function f() {
  return g(3);
}
f();

// 等同于
g(3);

上面的例子中函数的执行性能一样,很明显我们感受到,尾调用的使用,使代码的执行更加的快捷。

如果递归函数是尾调用自身,则称为尾递归。

在编码过程中,递归函数无疑是很消耗内存的,稍有不慎可能就会导致栈溢出的问题,但是如果使用尾调用优化递归,就不会有这个问题,这是因为使用尾调用优化的话,不管什么时候都只有一个调用帧,当然也就不会存在栈溢出的情况了。

function factorial(n) {
  if (n === 1) return 1;
  return n * factorial(n - 1);
}

factorial(5) // 120

上面的例子中是n的阶乘,函数复杂度是O(n)。

如果是尾递归

function factorial(n, total) {
  if (n === 1) return total;
  return factorial(n - 1, n * total);
}

factorial(5, 1) // 120

我们发现复杂度变为了O(1)。

尾调用的优化只有严格模式下才有用,如果正常模式下,其实在写递归的时候,我们应该是不到万不得已不使用递归的,有时候可以尽量想法变通使用循环来实现。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值