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 相关文章推荐
JSON JQUERY模板实现说明
Jul 03 Javascript
JavaScript 变量作用域分析
Jul 04 Javascript
js document.write()使用介绍
Feb 21 Javascript
禁用Tab键JS代码兼容Firefox和IE
Apr 18 Javascript
jQuery中position()方法用法实例
Jan 16 Javascript
JavaScript:Date类型全面解析
May 19 Javascript
原生js实现查询天气小应用
Dec 09 Javascript
详解用vue编写弹出框组件
Jul 04 Javascript
在小程序中使用canvas的方法示例
Sep 17 Javascript
深入浅析Vue 中 ref 的使用
Apr 29 Javascript
产制造追溯系统之通过微信小程序实现移动端报表平台
Jun 03 Javascript
vue radio单选框,获取当前项(每一项)的value值操作
Sep 10 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
jQuery中的RadioButton,input,CheckBox取值赋值实现代码
2014/02/18 PHP
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
PHP中使用循环实现的金字塔图形
2014/11/08 PHP
php函数实现判断是否移动端访问
2015/03/03 PHP
laravel框架模型中非静态方法也能静态调用的原理分析
2019/11/23 PHP
laravel 框架执行流程与原理简单分析
2020/02/01 PHP
完美解决JS中汉字显示乱码问题(已解决)
2006/12/27 Javascript
Javascript中的var_dump函数实现代码
2009/09/07 Javascript
jQuery对象[0]是什么含义?
2010/07/31 Javascript
JQuery中使用Ajax赋值给全局变量异常的解决方法
2014/01/10 Javascript
借助JavaScript脚本判断浏览器Flash Player信息的方法
2014/07/09 Javascript
node.js中的require使用详解
2014/12/15 Javascript
javascript实现俄罗斯方块游戏的思路和方法
2015/04/27 Javascript
javascript常用函数(1)
2015/11/04 Javascript
javascript鼠标跟随运动3种效果(眼球效果,苹果菜单,方向跟随)
2016/10/27 Javascript
vue2.X组件学习心得(新手必看篇)
2017/07/05 Javascript
解决ztree搜索中多级菜单展示不全问题
2017/07/05 Javascript
关于Vue源码vm.$watch()内部原理详解
2019/04/26 Javascript
使用vue实现HTML页面生成图片的方法
2020/03/12 Javascript
JavaScript常用工具函数库汇总
2020/09/17 Javascript
Python实现设置windows桌面壁纸代码分享
2015/03/28 Python
在Python的Flask框架中实现单元测试的教程
2015/04/20 Python
理解Python中的类与实例
2015/04/27 Python
[原创]Python入门教程1. 基本运算【四则运算、变量、math模块等】
2018/10/28 Python
python元组和字典的内建函数实例详解
2019/10/22 Python
浅谈pytorch卷积核大小的设置对全连接神经元的影响
2020/01/10 Python
在python下实现word2vec词向量训练与加载实例
2020/06/09 Python
Expedia爱尔兰:酒店、机票、租车及廉价假期
2017/01/02 全球购物
C语言中一个结构不能包含指向自己的指针吗
2012/05/25 面试题
什么是属性访问器
2015/10/26 面试题
几个MySql的面试题
2013/04/22 面试题
专科文秘应届生求职信
2013/11/18 职场文书
《故都的秋》教学反思
2014/04/15 职场文书
2014年路政工作总结
2014/12/10 职场文书
Java中Quartz高可用定时任务快速入门
2022/04/03 Java/Android
vue生命周期钩子函数以及触发时机
2022/04/26 Vue.js