JS尾递归的实现方法及代码优化技巧


Posted in Javascript onJanuary 19, 2019

本文实例讲述了JS尾递归的实现方法及代码优化技巧。分享给大家供大家参考,具体如下:

在学习数据结构和算法的时候,我们都知道所有的递归都是可以优化成栈+循环的。

对于特定的递归函数,一般我们都是手动对它们进行优化的。

在学习scala的时候,接触到尾递归的概念。我们只要将递归写成尾递归方式,编译器会自动帮助我们优化。

ps:并不是所有的递归都可以改写成尾递归

在js中,尾递归通常会被解释器优化。然而,并不是所有的js解释器都支持尾递归优化。

对于不支持尾递归优化的环境,我们需要手动将递归优化成栈+循环。

这里实现了一个通用的方法,将尾递归优化成栈+循环。

代码摘自阮一峰的《ECMAScript入门》这本书。

具体代码如下

function tco(f) {
  var value;
  var active = false;
  var accumulated = [];
  return function accumulator() {
    accumulated.push(arguments);
    if(!active) {
      active = true;
      while(accumulated.length) {
        value = f.apply(this, accumulated.shift());
      }
      active = false;
      return value;
    }
  };
}
var sum = tco(function(x, y) {
  if(y > 0) {
    return sum(x + 1, y - 1);
  } else {
    return x;
  }
});
let res = sum(1, 5)
console.info(res);

这段代码非常精妙!

分析

已知,任何递归可以写成循环+栈。

实现将任何尾递归转换成循环+栈执行而不需要针对每个尾递归函数写一个实现版本的思路。

困难在于,任何尾递归,通用实现。而不是针对某一个递归函数。

要点:

栈中保存的数据,正是递归函数的参数。

通用实现,那就必须依赖原来的递归函数,循环的终止条件,正是递归的结束条件。

要将递归函数的参数入栈,而不修改原来的递归函数,就必须用一个函数代替递归函数被调用,从而取得函数入参。

递归函数的终止条件,每一个递归函数都不一样,但是如果递归函数没有被再次调用,说明已达到终止条件。即终止条件和递归函数的调用有关联。而递归函数每次调用,都会将参数入栈。所以可以根据栈中是否有元素,推断是否达到终止条件。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JavaScript与C# Windows应用程序交互方法
Jun 29 Javascript
prototype 学习笔记整理
Jul 17 Javascript
高性能WEB开发 flush让页面分块,逐步呈现 flush让页面分块,逐步呈现
Jun 19 Javascript
IE6-IE9中tbody的innerHTML不能赋值的解决方法
Sep 26 Javascript
javascript截取字符串小结
Apr 28 Javascript
jQuery获取当前点击的对象元素(实现代码)
May 19 Javascript
Javascript vue.js表格分页,ajax异步加载数据
Oct 24 Javascript
微信小程序 地图(map)实例详解
Nov 16 Javascript
bootstrap使用validate实现简单校验功能
Dec 02 Javascript
微信小程序获取微信运动步数的实例代码
Jul 20 Javascript
微信小程序实现倒计时60s获取验证码
Apr 17 Javascript
JavaScript本地储存:localStorage、sessionStorage、cookie的使用
Oct 13 Javascript
javascriptvoid(0)含义以及与"#"的区别讲解
Jan 19 #Javascript
js实现延迟加载的几种方法详解
Jan 19 #Javascript
15分钟深入了解JS继承分类、原理与用法
Jan 19 #Javascript
js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解
Jan 19 #Javascript
js的各种数据类型判断的介绍
Jan 19 #Javascript
JavaScript实现与使用发布/订阅模式详解
Jan 19 #Javascript
Vuex中的State使用介绍
Jan 19 #Javascript
You might like
无线电波是什么?它是怎样传输的?
2021/03/01 无线电
PHP获得数组交集与差集的方法
2015/06/10 PHP
php开发时容易忘记的一些技术细节
2016/02/03 PHP
PHP模拟http请求的方法详解
2016/11/09 PHP
用js实现键盘方向键翻页功能的代码
2007/06/03 Javascript
ie 调试javascript的工具
2009/04/29 Javascript
jQuery自动切换/点击切换选项卡效果的小例子
2013/08/12 Javascript
Node.js安装教程和NPM包管理器使用详解
2014/08/16 Javascript
jquery用offset()方法获得元素的xy坐标
2014/09/06 Javascript
提交按钮的name='submit'引起的js失效问题及原因
2015/02/25 Javascript
JavaScript实现的多个图片广告交替显示效果代码
2015/09/04 Javascript
ECMA5数组的新增方法有哪些及forEach()模仿实现
2015/11/03 Javascript
详解node.js搭建代理服务器请求数据
2017/04/08 Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
2017/12/20 jQuery
微信小程序在其他页面监听globalData中值的变化
2019/07/15 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
2019/09/04 Javascript
vue实现输入框自动跳转功能
2020/05/20 Javascript
vscode 插件开发 + vue的操作方法
2020/06/05 Javascript
[10:04]国际邀请赛采访专栏:DK.Farseer,mouz.Black^,采访员Josh专访
2013/08/05 DOTA
布同自制Python函数帮助查询小工具
2011/03/13 Python
Python实现的石头剪子布代码分享
2014/08/22 Python
python写的一个squid访问日志分析的小程序
2014/09/17 Python
Python判断Abundant Number的方法
2015/06/15 Python
Python的包管理器pip更换软件源的方法详解
2016/06/20 Python
利用aardio给python编写图形界面
2017/08/21 Python
python GUI实现小球满屏乱跑效果
2019/05/09 Python
html5 冒号分隔符对齐的实现
2019/07/31 HTML / CSS
amaze ui 的使用详细教程
2020/08/19 HTML / CSS
美国最受欢迎的度假目的地优惠套餐:BookVIP
2018/09/27 全球购物
斯洛伐克电子产品购物网站:DATART
2020/04/05 全球购物
建筑工程技术专业求职信
2014/07/16 职场文书
工作收入证明范本
2015/06/12 职场文书
2019毕业典礼主持词!
2019/07/05 职场文书
新学期新寄语,献给新生们!
2019/11/15 职场文书
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏