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中运用闭包和自执行函数解决大量的全局变量问题
Dec 30 Javascript
javascript Array 数组常用方法
Apr 05 Javascript
jquery实现弹出层效果实例
May 19 Javascript
AngularJS Ajax详解及示例代码
Aug 17 Javascript
微信小程序入门教程
Nov 18 Javascript
JS克隆,属性,数组,对象,函数实例分析
Nov 26 Javascript
10个经典的网页鼠标特效代码
Jan 09 Javascript
深入理解Vue Computed计算属性原理
May 29 Javascript
浅谈Vue数据响应
Nov 05 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
Jan 29 Javascript
Element中Slider滑块的具体使用
Jul 29 Javascript
JavaScript实现复选框全选和取消全选
Nov 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
CodeIgniter框架URL路由总结
2014/09/03 PHP
PHPUnit安装及使用示例
2014/10/29 PHP
简介PHP的Yii框架中缓存的一些高级用法
2016/03/29 PHP
用PHP将Unicode 转化为UTF-8的实现方法(推荐)
2017/02/08 PHP
PHP中类型转换 ,常量,系统常量,魔术常量的详解
2017/10/26 PHP
PHP5.0~5.6 各版本兼容性cURL文件上传功能实例分析
2018/05/11 PHP
php post换行的方法
2020/02/03 PHP
JavaScript利用正则表达式去除日期中的-
2014/06/09 Javascript
使用JQuery实现的分页插件分享
2015/11/05 Javascript
jquery zTree异步加载简单实例讲解
2016/02/25 Javascript
jQuery EasyUI tree增加搜索功能的实现方法
2017/04/27 jQuery
老生常谈javascript的面向对象思想
2017/08/22 Javascript
vuex实现登录状态的存储,未登录状态不允许浏览的方法
2018/03/09 Javascript
JavaScript实现无限级递归树的示例代码
2019/03/29 Javascript
javascript面向对象创建对象的方式小结
2019/07/29 Javascript
JavaScript中的相等操作符使用详解
2019/12/21 Javascript
Ubuntu 14.04+Django 1.7.1+Nginx+uwsgi部署教程
2014/11/18 Python
详解Python字符串对象的实现
2015/12/24 Python
Python实现简单登录验证
2016/04/13 Python
Python中的Numpy矩阵操作
2018/08/12 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
Django使用模板后无法找到静态资源文件问题解决
2019/07/19 Python
python获取命令行参数实例方法讲解
2020/11/02 Python
JDK安装目录下有哪些内容
2014/08/25 面试题
如何利用find命令查找文件
2016/11/18 面试题
Linux的文件类型
2012/03/07 面试题
医学检验专业个人求职信范文
2013/12/04 职场文书
建筑专业自荐信范文
2014/01/05 职场文书
宿舍卫生检讨书
2014/01/16 职场文书
集体婚礼策划方案
2014/02/22 职场文书
大二学习计划书范文
2014/04/27 职场文书
2014三年级班主任工作总结
2014/12/05 职场文书
2016学习依法治国心得体会
2016/01/15 职场文书
使用GO语言实现Mysql数据库CURD的简单示例
2021/08/07 Golang
Python识别花卉种类鉴定网络热门植物并自动整理分类
2022/04/08 Python
js面向对象编程OOP及函数式编程FP区别
2022/07/07 Javascript