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 相关文章推荐
JavaScript代码简单实现求杨辉三角给定行的最大值
Oct 29 Javascript
javascript实现的登陆遮罩效果汇总
Nov 09 Javascript
JS实现随页面滚动显示/隐藏窗口固定位置元素
Feb 26 Javascript
基于js实现checkbox批量选中操作
Nov 22 Javascript
jQuery EasyUI 页面加载等待及页面等待层
Feb 06 Javascript
浅谈JavaScript的innerWidth与innerHeight
Oct 12 Javascript
swiper自定义分页器使用方法详解
Sep 14 Javascript
Vue.js 利用v-for中的index值实现隔行变色
Aug 01 Javascript
bootstrap table合并行数据并居中对齐效果
Oct 17 Javascript
Vue3+elementui plus创建项目的方法
Dec 01 Vue.js
在vue中使用inheritAttrs实现组件的扩展性介绍
Dec 07 Vue.js
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
收音机鉴频器对声音的影响和频偏分析
2021/03/02 无线电
PHP中auto_prepend_file与auto_append_file用法实例分析
2014/09/22 PHP
PHP获取不了React Native Fecth参数的解决办法
2016/08/26 PHP
php 实现简单的登录功能示例【基于thinkPHP框架】
2019/12/02 PHP
PHP fopen中文文件名乱码问题解决方案
2020/10/28 PHP
Prototype使用指南之range.js
2007/01/10 Javascript
Javascript的常规数组和关联数组对比小结
2012/05/24 Javascript
jQuery实现仿美橙互联两级导航菜单效果完整实例
2015/09/17 Javascript
JQuery中Ajax()的data参数类型实例分析
2015/12/15 Javascript
拥Bootstrap入怀——导航栏篇
2016/05/30 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
2017/01/05 Javascript
easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大的实现代码
2017/01/12 Javascript
微信小程序开发之数据存储 参数传递 数据缓存
2017/04/13 Javascript
vue+iview+less 实现换肤功能
2018/08/17 Javascript
原生JS实现汇率转换功能代码实例
2020/05/13 Javascript
写一个Vue loading 插件
2020/11/09 Javascript
python PrettyTable模块的安装与简单应用
2019/01/11 Python
django Admin文档生成器使用详解
2019/07/22 Python
python实现的接收邮件功能示例【基于网易POP3服务器】
2019/09/11 Python
Python全栈之列表数据类型详解
2019/10/01 Python
基于python的itchat库实现微信聊天机器人(推荐)
2019/10/29 Python
python类中super() 的使用解析
2019/12/19 Python
Pytorch基本变量类型FloatTensor与Variable用法
2020/01/08 Python
css3加js做一个简单的3D行星运转效果实例代码
2017/01/18 HTML / CSS
css3实现小箭头各种图形效果
2020/07/08 HTML / CSS
法学毕业生自我鉴定
2014/01/31 职场文书
网络营销策划方案
2014/06/04 职场文书
会计专业求职信
2014/08/10 职场文书
2014年党员自我评议对照检查材料
2014/09/20 职场文书
公司党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
践行党的群众路线心得体会
2014/11/05 职场文书
代理词怎么写
2015/05/25 职场文书
欢迎新生标语2015
2015/07/16 职场文书
postgresql使用filter进行多维度聚合的解决方法
2021/07/16 PostgreSQL
如何避免mysql启动时错误及sock文件作用分析
2022/01/22 MySQL
python opencv将多个图放在一个窗口的实例详解
2022/02/28 Python