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 相关文章推荐
AJAX异步从优酷专辑中采集所有视频及信息(JavaScript代码)
Nov 20 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
Apr 22 Javascript
JS JSON对象转为字符串的简单实现方法
Nov 18 Javascript
document.forms[].submit()使用介绍
Feb 19 Javascript
Bootstrap的基本应用要点浅析
Dec 19 Javascript
Angular.js跨controller实现参数传递的两种方法
Feb 20 Javascript
JavaScript事件冒泡与事件捕获实例分析
Aug 01 Javascript
Vue实现动态添加或者删除对象和对象数组的操作方法
Sep 21 Javascript
对angularJs中2种自定义服务的实例讲解
Sep 30 Javascript
jQuery+PHP实现上传裁剪图片
Jun 29 jQuery
使vue实现jQuery调用的两种方法
May 12 jQuery
在Uni中使用Vue的EventBus总线机制操作
Jul 31 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
destoon在各个服务器下设置URL Rewrite(伪静态)的方法
2014/06/21 Servers
PHP扩展开发入门教程
2015/02/26 PHP
PHP二维关联数组的遍历方式(实例讲解)
2017/10/18 PHP
PHP实现一个按钮点击上传多个图片操作示例
2020/01/23 PHP
js中cookie的使用详细分析
2008/05/28 Javascript
js模拟select下拉菜单控件的代码
2013/05/08 Javascript
使用js操作cookie的一点小收获分享
2013/09/03 Javascript
js动态删除div元素基本思路及实现代码
2014/05/08 Javascript
IE下使用jQuery重置iframe地址时内存泄露问题解决办法
2015/02/05 Javascript
js实现文本框宽度自适应文本宽度的方法
2015/08/13 Javascript
Bootstrap CSS组件之按钮组(btn-group)
2016/12/17 Javascript
jquery replace方法去空格
2017/05/08 jQuery
BootStrap数据表格实例代码
2017/09/13 Javascript
vue弹窗消息组件的使用方法
2020/09/24 Javascript
ES6顶层对象、global对象实例分析
2019/06/14 Javascript
vue项目中使用AES实现密码加密解密(ECB和CBC两种模式)
2019/08/12 Javascript
详解Vue的七种传值方式
2021/02/08 Vue.js
python简单判断序列是否为空的方法
2015/06/30 Python
windows环境下tensorflow安装过程详解
2018/03/30 Python
Python3对称加密算法AES、DES3实例详解
2018/12/06 Python
python调用matplotlib模块绘制柱状图
2019/10/18 Python
Python FtpLib模块应用操作详解
2019/12/12 Python
Python创建简单的神经网络实例讲解
2021/01/04 Python
基于 HTML5 Canvas实现 的交互式地铁线路图
2018/03/05 HTML / CSS
html5 Canvas画图教程(5)—canvas里画曲线之arc方法
2013/01/09 HTML / CSS
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
初中美术教学反思
2014/01/29 职场文书
业务部门经理岗位职责
2014/02/23 职场文书
《画》教学反思
2014/04/14 职场文书
春季防火方案
2014/05/10 职场文书
2015年普法依法治理工作总结
2015/05/26 职场文书
孔繁森观后感
2015/06/10 职场文书
python 解决微分方程的操作(数值解法)
2021/05/26 Python
Jackson 反序列化时实现大小写不敏感设置
2021/06/29 Java/Android
Android基础入门之dataBinding的简单使用教程
2022/06/21 Java/Android
前端框架ECharts dataset对数据可视化的高级管理
2022/12/24 Javascript