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 相关文章推荐
jquery 插件开发方法小结
Oct 23 Javascript
js 操作select与option(示例讲解)
Dec 20 Javascript
JS控制表单提交的方法
Jul 09 Javascript
jquery模拟进度条实现方法
Aug 03 Javascript
jQuery实现二级下拉菜单效果
Jan 05 Javascript
jquery实现可旋转可拖拽的文字效果代码
Jan 27 Javascript
JavaScript闭包实例详解
Jun 03 Javascript
AngularJS路由Ui-router模块用法示例
May 29 Javascript
vue-cli配置文件——config篇
Jan 04 Javascript
浅谈Webpack 持久化缓存实践
Mar 22 Javascript
详细介绍解决vue和jsp结合的方法
Feb 06 Javascript
微信小程序自定义modal弹窗组件的方法详解
Dec 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脚本数据库功能详解(中)
2006/10/09 PHP
用PHP调用Oracle存储过程的方法
2008/09/12 PHP
详解PHP导入导出CSV文件
2014/11/03 PHP
JavaScript基本对象
2007/01/11 Javascript
关于juqery radio写法的兼容性问题(新老版本jquery)
2010/06/14 Javascript
js/jquery判断浏览器类型的方法小结
2015/05/12 Javascript
详解JavaScript正则表达式中的global属性的使用
2015/06/16 Javascript
jQuery实现网站添加高亮突出显示效果的方法
2015/06/26 Javascript
JavaScript高级教程5.6之基本包装类型(详细)
2015/11/23 Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
2016/10/11 Javascript
纯js模仿windows系统日历
2017/02/04 Javascript
JavaScript数据结构之双向链表和双向循环链表的实现
2017/11/28 Javascript
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
2018/06/05 jQuery
vue项目中监听手机物理返回键的实现
2020/01/18 Javascript
Javascript原型链及instanceof原理详解
2020/05/25 Javascript
vue实现简易图片左右旋转,上一张,下一张组件案例
2020/07/31 Javascript
[00:32]2018DOTA2亚洲邀请赛EG出场
2018/04/03 DOTA
python基础教程之Hello World!
2014/08/29 Python
python实现m3u8格式转换为mp4视频格式
2018/02/28 Python
Python获取系统所有进程PID及进程名称的方法示例
2018/05/24 Python
python编程使用协程并发的优缺点
2018/09/20 Python
详解Python传入参数的几种方法
2019/05/16 Python
Python使用itchat模块实现简单的微信控制电脑功能示例
2019/08/26 Python
Python实现把类当做字典来访问
2019/12/16 Python
Python 爬虫批量爬取网页图片保存到本地的实现代码
2020/12/24 Python
Python 爬取淘宝商品信息栏目的实现
2021/02/06 Python
使用HTML5 Geolocation实现一个距离追踪器
2018/04/09 HTML / CSS
为奢侈时尚带来了慈善元素:Olivela
2018/09/29 全球购物
竞聘上岗演讲稿范文
2014/01/10 职场文书
幼儿园教师培训制度
2014/01/16 职场文书
2014年父亲节活动方案
2014/03/06 职场文书
二年级语文上册复习计划
2015/01/19 职场文书
供应商食品安全承诺书
2015/04/29 职场文书
Vue的列表之渲染,排序,过滤详解
2022/02/24 Vue.js
【海涛教你打DOTA】剑圣第一人称视角解说
2022/04/01 DOTA
Nginx 配置 HTTPS的详细过程
2022/05/30 Servers