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 相关文章推荐
动态创建的表格单元格中的事件实现代码
Dec 30 Javascript
JavaScript中清空数组的三种方法分享
Apr 07 Javascript
jquery键盘事件使用介绍
Nov 01 Javascript
情人节之礼 js项链效果
Feb 13 Javascript
JavaScript将数字转换成大写中文的方法
Mar 23 Javascript
使用CoffeeScrip优美方式编写javascript代码
Oct 28 Javascript
jquery日历插件datepicker用法分析
Jan 22 Javascript
JavaScript面试题大全(推荐)
Sep 22 Javascript
微信小程序 require机制详解及实例代码
Dec 14 Javascript
jQuery插件HighCharts绘制的2D堆柱状图效果示例【附demo源码下载】
Mar 14 Javascript
通过jquery获取上传文件名称、类型和大小的实现代码
Apr 19 jQuery
ES6关于Promise的用法详解
May 07 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
全国FM电台频率大全 - 4 山西省
2020/03/11 无线电
PHP 日志缩略名的创建函数代码
2010/05/26 PHP
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
php隐藏实际地址的文件下载方法
2015/04/18 PHP
Smarty缓存机制实例详解【三种缓存方式】
2019/07/20 PHP
javascript 兼容鼠标滚轮事件
2009/04/07 Javascript
js 面向对象的技术创建高级 Web 应用程序
2010/02/25 Javascript
ASP.NET MVC中EasyUI的datagrid跨域调用实现代码
2012/03/14 Javascript
caller和callee的区别介绍及演示结果
2013/03/10 Javascript
jquery判断至少有一个checkbox被选中的方法
2015/06/05 Javascript
jQuery Validation Plugin验证插件手动验证
2016/01/26 Javascript
Boostrap模态窗口的学习小结
2016/03/28 Javascript
jQuery中hover方法搭配css的hover选择器,实现选中元素突出显示方法
2017/05/08 jQuery
完美解决手机浏览器顶部下拉出现网页源或刷新的问题
2017/11/30 Javascript
vue项目webpack中Npm传递参数配置不同域名接口
2018/06/15 Javascript
在Vue 中使用Typescript的示例代码
2018/09/10 Javascript
详解webpack4之splitchunksPlugin代码包分拆
2018/12/04 Javascript
vue.js实现照片放大功能
2020/06/23 Javascript
Vue props中Object和Array设置默认值操作
2020/07/30 Javascript
[59:07]海涛为你详解DOTA2新版本“贤哲秘契”
2014/11/22 DOTA
[50:22]完美盛典-2018年度红毯走秀
2018/12/16 DOTA
[01:02:26]DOTA2-DPC中国联赛 正赛 SAG vs RNG BO3 第二场 1月18日
2021/03/11 DOTA
python 实现识别图片上的数字
2019/07/30 Python
Mac安装python3的方法步骤
2019/08/09 Python
Python 3.6 中使用pdfminer解析pdf文件的实现
2019/09/25 Python
python-web根据元素属性进行定位的方法
2019/12/13 Python
网络、C以及其他硬件方面的面试题
2016/08/23 面试题
公务员职业生涯规划书范文  
2014/01/19 职场文书
受伤赔偿协议书
2014/09/24 职场文书
政风行风建设整改方案
2014/10/27 职场文书
狂人日记读书笔记
2015/06/30 职场文书
员工规章制度范本
2015/08/07 职场文书
2019年干货:自我鉴定
2019/03/25 职场文书
OpenCV实现普通阈值
2021/11/17 Java/Android
Kubernetes中Deployment的升级与回滚
2022/04/01 Servers
Android在Sqlite3中的应用及多线程使用数据库的建议
2022/04/24 Java/Android