es6函数之尾调用优化实例分析


Posted in Javascript onApril 25, 2020

本文实例讲述了es6函数之尾调用优化。分享给大家供大家参考,具体如下:

什么是尾调用优化?

尾调用是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

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

上面代码中,函数f的最后一步是调用函数g,这就叫尾调用。

以下三种情况,都不属于尾调用。

// 情况一
function f(x) {
 let y = g(x)
 return y
}
// 情况二
function f(x) {
 return g(x) + 1
}
// 情况三
function f(x) {
 g(x)
}

尾调用不一定出现在函数尾部,只要是最后一步操作即可。

function f(x) {
 if (x > 0) {
  return m(x)
 }
 return n(x);
}

尾调用之所以与其他调用不同,就在于它的特殊的调用位置。

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

尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置,内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。

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

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

// 等同于
g(3);

上面代码中,如果函数g不是尾调用,函数f就需要保存内部变量m和n的值、g的调用位置等信息。但由于调用g之后,函数f就结束了,所以执行到最后一步,完全可以删除f(x)的调用帧,只保留g(3)的调用帧。

这就叫做“尾调用优化”(Tail call optimization),即只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优化”的意义。

注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。

function addOne(a){
 var one = 1;
 function inner(b){
  return b + one;
 }
 return inner(a);
}

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
js保留两位小数使用toFixed实现
Jul 29 Javascript
常用DOM整理
Jun 16 Javascript
简单实现JS对dom操作封装
Dec 02 Javascript
推荐阅读的js快速判断IE浏览器(兼容IE10与IE11)
Dec 13 Javascript
JS动态创建元素的两种方法
Apr 20 Javascript
JS实现的样式切换功能tableCSS实例
Dec 30 Javascript
js中字符型和数值型数字的互相转化方法(必看)
Apr 25 Javascript
JavaScript禁止微信浏览器下拉回弹效果
May 16 Javascript
angularJS实现不同视图同步刷新详解
Oct 09 Javascript
详解JS实现简单的时分秒倒计时代码
Apr 25 Javascript
多个Vue项目部署到服务器的步骤记录
Oct 22 Javascript
html5调用摄像头截图功能
Jan 18 Javascript
es6函数之尾递归用法实例分析
Apr 25 #Javascript
javascript 易错知识点实例小结
Apr 25 #Javascript
javascript执行上下文、变量对象实例分析
Apr 25 #Javascript
JavaScript ECMA-262-3 深入解析(二):变量对象实例详解
Apr 25 #Javascript
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
Apr 25 #Javascript
使用 Jest 和 Supertest 进行接口端点测试实例详解
Apr 25 #Javascript
javascript 函数的暂停和恢复实例详解
Apr 25 #Javascript
You might like
PHP实现绘制3D扇形统计图及图片缩放实例
2014/10/01 PHP
基于递归实现的php树形菜单代码
2014/11/19 PHP
thinkphp3.2.2实现生成多张缩略图的方法
2014/12/19 PHP
PHP递归算法的简单实例
2019/02/28 PHP
JavaScript iframe的相互操作浅析
2009/10/14 Javascript
jQuery焦点图切换特效插件封装实例
2013/08/18 Javascript
防止登录页面出现在frame中js代码
2014/07/22 Javascript
jquery中each遍历对象和数组示例
2014/08/05 Javascript
jquery实现搜索框常见效果的方法
2015/01/22 Javascript
Bootstrap3 Grid system原理及应用详解
2016/09/30 Javascript
node.js实现复制文本到剪切板的功能
2017/01/23 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
2017/06/11 jQuery
three.js中文文档学习之如何本地运行详解
2017/11/20 Javascript
新手快速上手webpack4打包工具的使用详解
2019/01/28 Javascript
实例讲解v-if和v-show的区别
2019/01/31 Javascript
JS通用方法触发点击事件代码实例
2020/02/17 Javascript
使用Vue 自定义文件选择器组件的实例代码
2020/03/04 Javascript
vue+canvas实现拼图小游戏
2020/09/18 Javascript
ant design pro中可控的筛选和排序实例
2020/11/17 Javascript
[39:32]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS DT 第二场
2014/05/23 DOTA
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
Python文本处理之按行处理大文件的方法
2018/04/09 Python
python 使用re.search()筛选后 选取部分结果的方法
2018/11/28 Python
用Python中的turtle模块画图两只小羊方法
2019/04/09 Python
我就是这样学习Python中的列表
2019/06/02 Python
关于Python 常用获取元素 Driver 总结
2019/11/24 Python
使用Keras中的ImageDataGenerator进行批次读图方式
2020/06/17 Python
django数据模型中null和blank的区别说明
2020/09/02 Python
CAT鞋美国官网:CAT Footwear
2017/11/27 全球购物
寻找迷宫的一条出路,o通路;X:障碍
2016/07/10 面试题
简历自我评价怎么写好呢?
2014/01/04 职场文书
广告创意求职信
2014/03/17 职场文书
家长通知书教师评语
2014/04/17 职场文书
学校就业推荐信范文
2014/05/19 职场文书
公司门卫工作职责
2014/06/28 职场文书
喋血孤城观后感
2015/06/08 职场文书