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 相关文章推荐
input 高级限制级用法
Mar 26 Javascript
jQuery 方法大全方便学习参考
Feb 25 Javascript
利用JS来控制键盘的上下左右键(示例代码)
Dec 14 Javascript
jQuery简易图片放大特效示例代码
Jun 09 Javascript
jQuery中unbind()方法用法实例
Jan 19 Javascript
理解JavaScript事件对象
Jan 25 Javascript
Bootstrap3 Grid system原理及应用详解
Sep 30 Javascript
JS常用函数和常用技巧小结
Oct 15 Javascript
微信小程序 跳转方式总结
Apr 20 Javascript
D3.js的基础部分之数组的处理数组的排序和求值(v3版本)
May 09 Javascript
深入理解webpack process.env.NODE_ENV配置
Feb 23 Javascript
react国际化react-intl的使用
May 06 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
如何限制访问者的ip(PHPBB的代码)
2006/10/09 PHP
php中的boolean(布尔)类型详解
2013/10/28 PHP
Yii2 中实现单点登录的方法
2018/03/09 PHP
PHP中单例模式的使用场景与使用方法讲解
2019/03/18 PHP
javascript flash下fromCharCode和charCodeAt方法使用说明
2008/01/12 Javascript
使用jQuery.Validate进行客户端验证(初级篇) 不使用微软验证控件的理由
2010/06/28 Javascript
潜说js对象和数组
2011/05/25 Javascript
jquery attr 设定src中含有&(宏)符号问题的解决方法
2011/07/26 Javascript
基于JQuery的多标签实现代码
2012/09/19 Javascript
Javascript计算两个marker之间的距离(Google Map V3)
2013/04/26 Javascript
基于javascript实现tab选项卡切换特效调试笔记
2016/03/30 Javascript
jQuery实现漂亮实用的商品图片tips提示框效果(无图片箭头+阴影)
2016/04/16 Javascript
Vue.js在使用中的一些注意知识点
2017/04/29 Javascript
快速解决处理后台返回json数据格式的问题
2018/08/07 Javascript
vue-cli 首屏加载优化问题
2018/11/06 Javascript
微信小程序实现电子签名并导出图片
2020/05/27 Javascript
vue中v-model对select的绑定操作
2020/08/31 Javascript
vue3.0封装轮播图组件的步骤
2021/03/04 Vue.js
在Django的session中使用User对象的方法
2015/07/23 Python
Django自定义分页效果
2017/06/27 Python
Django ORM框架的定时任务如何使用详解
2017/10/19 Python
详解python函数传参是传值还是传引用
2018/01/16 Python
Python中format()格式输出全解
2019/04/12 Python
检测python爬虫时是否代理ip伪装成功的方法
2019/07/12 Python
修改 CentOS 6.x 上默认Python的方法
2019/09/06 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
Timberland俄罗斯官方网上商店:全球领先的户外品牌
2020/03/15 全球购物
求最大连续递增数字串(如"ads3sl456789DF3456ld345AA"中的"456789")
2015/09/11 面试题
初中同学聚会感言
2014/02/11 职场文书
英语国培研修感言
2014/02/13 职场文书
2014年银行员工年终自我评价
2014/09/19 职场文书
幼儿园欢迎词范文
2015/01/26 职场文书
2015年收银员个人工作总结
2015/04/01 职场文书
导游词之西安骊山
2019/12/20 职场文书
Redis调用Lua脚本及使用场景快速掌握
2022/03/16 Redis
VMware虚拟机安装 Windows Server 2022的详细图文教程
2022/09/23 Servers