JS尾调用优化

6 篇文章 0 订阅

1. 写在前面

上次介绍了什么是尾调用以及怎么准确快速的判别一个函数调用是否为尾调用。那么,我们判别尾调用的意义是什么呢?做什么事情总归有个目的,那么今天我们就来系统的介绍一下尾调用的意义,或者说尾调用有什么用吧。

2. 尾调用优化

我们知道,函数的调用会在内存中生成一个“调用帧”(call frame),保存着函数的调用位置和内部变量等信息。如果在函数A的内部调用函数B,那么在A的调用帧上方还会生成一个B的调用帧。等到函数B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B的内部还调用函数C,那么在B的调用帧上方又会生成一个C的调用帧,以此类推。所有的调用帧就形成了一个“调用栈”(call stack)。

我们知道,尾调用是函数的最后一步操作,外部函数的调用位置和其内部变量信息都不会再用到了,所以不需要保留外部函数的调用帧了,直接用内层函数的调用帧取代外层函数的调用帧即可。

如果所有的函数都是尾调用,那么完全可以做到每次执行时的调用帧只有一项,这将大大的节省内存,更不可能发生内存溢出,这就是讨论尾调用的意义所在。

所谓的“尾调用优化”,其实就是保证在函数执行时只保留内层函数的调用帧,换句话说,就是用内层函数的调用帧取代外部函数的调用帧,即执行时内存中只保存一项调用帧。

3. 如何做到尾调用优化

通过上面的讨论,我们知道了,只要外部函数的调用帧被内层函数的调用帧取代即可做到“尾调用优化”。同时,我们也知道调用帧是用来保存函数调用位置和内部变量信息的,所以,要想让内层函数的调用帧取代外部函数的调用帧,只需要保证,在调用内层函数时,不再用到和外部函数有关的一切信息即可(不再用到外部函数的内部变量)。

如此,我们总结出只有内层函数在被调用时不再用到外部函数的内部变量,才能做到“尾调用优化”。

先来,看一个例子:

function f(a) {
    var b = 3;
    function g(n) {
      return n + b
    }
    return g(a)
}

上述例子,我们明显可以看出这是典型的尾调用,那么这有没有做到“尾调用优化”呢?很明显,可以看出在调用内部函数g的时候,其内部用到外部函数f 的内部变量b,故在函数g 被调用时,g 的调用帧并不能取代外部函数f 的调用帧,所以这不是“尾调用优化”。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值