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 相关文章推荐
escape、encodeURI 和 encodeURIComponent 的区别
Mar 02 Javascript
使用JQuery和s3captche实现一个水果名字的验证
Aug 14 Javascript
JavaScript通过正则表达式实现表单验证电话号码
Mar 07 Javascript
什么是Node.js?Node.js详细介绍
Jun 01 Javascript
基于Echarts 3.19 制作常用的图形(非静态)
May 19 Javascript
AngularJS入门教程之Cookies读写操作示例
Nov 02 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
Dec 07 Javascript
Vue2组件tree实现无限级树形菜单
Mar 29 Javascript
zTree获取当前节点的下一级子节点数实例
Sep 05 Javascript
微信小程序picker组件关于objectArray数据类型的绑定方法
Mar 13 Javascript
Vue中的组件及路由使用实例代码详解
May 22 Javascript
精读《Vue3.0 Function API》
May 20 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中=赋值操作符对不同数据类型的不同行为
2011/01/02 PHP
如何在symfony中导出为CSV文件中的数据
2011/10/06 PHP
php实现的支持断点续传的文件下载类
2014/09/23 PHP
php数组指针操作详解
2017/02/14 PHP
javascript div 遮罩层封锁整个页面
2009/07/10 Javascript
使用原生javascript创建通用表单验证——更锋利的使用dom对象
2011/09/13 Javascript
jQuery简单创建节点的方法
2016/09/09 Javascript
基于JS快速实现导航下拉菜单动画效果附源码下载
2016/10/27 Javascript
js实现的简练高效拖拽功能示例
2016/12/21 Javascript
nodejs读写json文件的简单方法(必看)
2017/03/09 NodeJs
使用jquery datatable和bootsrap创建表格实例代码
2017/03/17 Javascript
Node.js中的http请求客户端示例(request client)
2017/05/04 Javascript
js原生日历的实例(推荐)
2017/10/31 Javascript
讲解vue-router之什么是嵌套路由
2018/05/28 Javascript
JS实现判断数组是否包含某个元素示例
2019/05/24 Javascript
Layui弹框中数据表格中可双击选择一条数据的实现
2020/05/06 Javascript
Object.keys() 和 Object.getOwnPropertyNames() 的区别详解
2020/05/21 Javascript
Python pass 语句使用示例
2014/03/11 Python
教你用python3根据关键词爬取百度百科的内容
2016/08/18 Python
如何实现删除numpy.array中的行或列
2018/05/08 Python
学python安装的软件总结
2019/10/12 Python
Python数据可视化:泊松分布详解
2019/12/07 Python
python sklearn包——混淆矩阵、分类报告等自动生成方式
2020/02/28 Python
使用matlab 判断两个矩阵是否相等的实例
2020/05/11 Python
css3动画事件—webkitAnimationEnd与计时器time事件
2013/01/31 HTML / CSS
施华洛世奇中国官网:SWAROVSKI中国
2020/06/16 全球购物
公务员个人自我评价分享
2013/11/06 职场文书
基层干部2014全国两会学习心得体会
2014/03/10 职场文书
绩效工资实施方案
2014/03/15 职场文书
入职担保书范文
2014/05/21 职场文书
音乐教师求职信
2014/06/28 职场文书
2016春季田径运动会广播稿
2015/12/21 职场文书
创业计划之特色精品店
2019/08/12 职场文书
pandas中对文本类型数据的处理小结
2021/11/01 Python
Python MNIST手写体识别详解与试练
2021/11/07 Python
JavaScript圣杯布局与双飞翼布局实现案例详解
2022/08/05 Javascript