[js] 举例说明js中什么是尾调用优化

  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 的调用帧,所以这不是“尾调用优化”。

个人简介

我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易,
但坚持一定很酷。欢迎大家一起讨论

主目录

与歌谣一起通关前端面试题

[js] 举例说明js中什么是尾调用优化相关推荐

  1. [js] 举例说明js立即执行函数的写法有哪些?

    [js] 举例说明js立即执行函数的写法有哪些? 1.(function(){ //code }())2.!function(){ //code }()3.!(function(){ //code } ...

  2. 递归循环一个无限极数组_理解递归、尾调用优化和蹦床函数优化

    想要理解递归,您必须先理解递归.开个玩笑罢了, 递归 是一种编程技巧,它可以让函数在不使用 for 或 while 的情况下,使用一个调用自身的函数来实现循环. 例子 1:整数总和 例如,假设我们想要 ...

  3. 尾调用优化 java_基于Java8函数式编程求一个List的全部子集|尾调用优化解决递归性能问题...

    目录 基于函数式编程求一个List的全部子集 代码来自<Java8 in Action>,思路和其他递归解决方法一致,但不同的地方在concat方法 public static List& ...

  4. 什么是尾调用优化和尾递归?

    尾调用:某个函数的最后一步是调用另一个函数. 尾递归:如果尾调用自身,则是尾递归. 尾调用优化: 函数调用会在内存中形成一个"调用记录",又称为"调用帧",保存 ...

  5. 尾调用优化 java_为什么JVM仍然不支持尾调用优化?

    拉丁的传说 也许您已经知道这一点,但是这个功能并不像听起来那么简单,因为Java语言实际上将堆栈跟踪暴露给程序员.考虑以下程序:public class Test { public static St ...

  6. javascript --- 函数的优化(尾调用优化)

    从一个熟悉的Fibonacci数列的实现开始: function Fibonacci (n) {if ( n <= 1) { return 1};return Fibonacci(n -1) + ...

  7. ondestroy什么时候调用_尾调用和尾递归

    尾调用 1. 定义 尾调用是函数式编程中一个很重要的概念,当一个函数执行时的最后一个步骤是返回另一个函数的调用,这就叫做尾调用. 注意这里函数的调用方式是无所谓的,以下方式均可: 函数调用: func ...

  8. ES6 尾调用和尾递归优化

    尾调用 尾调用(Tail Call)是函数式编程的一个重要概念,就是指某个函数的最后一步是调用另一个函数. function fun(x){return a(x); } 上面代码中,函数fun的最后一 ...

  9. 【恋上数据结构】递归(函数调用过程、斐波那契数列、上楼梯、汉诺塔、递归转非递归、尾调用)

    递归(Recursion) 什么是递归? 函数的调用过程(栈空间) 函数的递归调用过程 递归实例分析(1 + 2 + 3 + ... + 100 的和) 递归的基本思想.使用套路 斐波那契数列 fib ...

最新文章

  1. [论文泛读] QoS论文两篇(Elsevier09, IEEE05)
  2. python 使用记录
  3. 我的Android进阶之旅------gt;Android中MediaRecorder.stop()报错 java.lang.RuntimeException: stop failed....
  4. CentOS通过DNSpod实现动态域名
  5. 机器人学习--从路径规划侧面看栅格地图
  6. 《Python快速入门》6大数据类型详解
  7. 协议簇:Ethernet Address Resolution Protocol (ARP) 解析
  8. 如何系统的自学python-如何系统地自学Python
  9. javascript 阮一峰入门教程
  10. (转)GB2312简体中文编码表
  11. 在word文档中添加上角标和下角标
  12. android logo在线生成工具,在线生成logo
  13. 温度传感器—LM75
  14. Android memery data sample
  15. 打开计算机管理的常用方法,电脑中的“计算机管理”界面打开方法大全
  16. 用c语言编写编码菲诺,大C论表:MKS柏涛菲诺150周年纪念款带来哪些升级
  17. linux qq 中文输入法下载,百度输入法Linux版
  18. [转]JAVA环境变量设置完全版
  19. 简报 | 印度政府最终确定加密货币监管框架
  20. 解决找不到GL/gl.h的问题

热门文章

  1. PopupMenu控件的使用
  2. 矩阵快速幂及斐波那契数列模板
  3. 深入分析Spring 与 Spring MVC容器
  4. HBuilder完成webApp入门(2)
  5. 在VisualStadio2015上使用EF6.0建立MySql数据库
  6. codeforce Gym 100500F Door Lock (二分)
  7. 基础【循环】-----(枚举器)------(转)
  8. android 百度地图3.0,android 百度地图3.0
  9. 无限复活服务器,绝地求生无限复活模式怎么玩 无限复活新手教程
  10. python函数对变量的作用_python函数对变量的作用及遵循的原则