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 相关文章推荐
Firefox+FireBug使JQuery的学习更加轻松愉快
Jan 01 Javascript
JS+DIV+CSS实现的经典标签切换效果代码
Sep 14 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
Oct 16 Javascript
Bootstrap多级导航栏(级联导航)的实现代码
Mar 08 Javascript
Vue.js Ajax动态参数与列表显示实现方法
Oct 20 Javascript
基于Angularjs+mybatis实现二级评论系统(仿简书)
Feb 13 Javascript
vue子组件使用自定义事件向父组件传递数据
May 27 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
Nov 09 Javascript
小程序实现列表多个批量倒计时
Jan 29 Javascript
详解小程序云开发数据库
May 20 Javascript
Vue用mixin合并重复代码的实现
Nov 27 Vue.js
微信小程序实现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/11/24 PHP
php xml文件操作实现代码(二)
2009/03/20 PHP
PHP计划任务、定时执行任务的实现代码
2011/04/23 PHP
PHP fgetcsv 定义和用法(附windows与linux下兼容问题)
2012/05/29 PHP
Zend Framework中的简单工厂模式 图文
2012/07/10 PHP
PHP mysqli事务操作常用方法分析
2017/07/22 PHP
PHP实现与java 通信的插件使用教程
2019/08/11 PHP
js验证表单第二部分
2006/11/25 Javascript
关于Javascript模块化和命名空间管理的问题说明
2010/12/06 Javascript
jQuery源码分析-05异步队列 Deferred 使用介绍
2011/11/14 Javascript
JavaScript函数中关于valueOf和toString的理解
2016/06/14 Javascript
基于jQuery实现一个marquee无缝滚动的插件
2017/03/09 Javascript
浅谈AngularJs 双向绑定原理(数据绑定机制)
2017/12/07 Javascript
javaScript中的空值和假值
2017/12/18 Javascript
关于ES6箭头函数中的this问题
2018/02/27 Javascript
node基于puppeteer模拟登录抓取页面的实现
2018/05/09 Javascript
使用vue实现各类弹出框组件
2019/07/03 Javascript
vue项目中实现缓存的最佳方案详解
2019/07/11 Javascript
使用layui日期控件laydate对开始和结束时间进行联动控制的方法
2019/09/06 Javascript
使用Vue实现调用接口加载页面初始数据
2019/10/28 Javascript
基于vue 动态菜单 刷新空白问题的解决
2020/08/06 Javascript
[06:06]2018DOTA2亚洲邀请赛主赛事第四日战况回顾 全明星赛欢乐上演
2018/04/07 DOTA
Django学习笔记之为Model添加Action
2019/04/30 Python
PyQt5 加载图片和文本文件的实例
2019/06/14 Python
Asics日本官网:鬼冢八喜郎创立的跑鞋运动品牌
2017/10/18 全球购物
Johnston & Murphy官网: 约翰斯顿·墨菲牛津总统鞋
2018/01/09 全球购物
美国葡萄酒网上商店:Martha Stewart Wine Co.
2019/03/17 全球购物
数控技校生自我鉴定
2014/04/19 职场文书
2014年国庆标语
2014/06/30 职场文书
教师个人培训总结
2015/02/11 职场文书
师范生小学见习总结
2015/06/23 职场文书
小组口号霸气押韵
2015/12/24 职场文书
Python中快速掌握Data Frame的常用操作
2021/03/31 Python
CSS3 制作的书本翻页特效
2021/04/13 HTML / CSS
goland 设置project gopath的操作
2021/05/06 Golang
Python可视化学习之matplotlib内置单颜色
2022/02/24 Python