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 相关文章推荐
创建一个复制UBB软件信息的链接或按钮的js代码
Jan 06 Javascript
jQuery中的.bind()、.live()和.delegate()之间区别分析
Jun 08 Javascript
jquery自定义插件——window的实现【示例代码】
May 06 Javascript
使用jQuery5分钟快速搞定双色表格的简单实例
Aug 08 Javascript
JS 滚动事件window.onscroll与position:fixed写兼容IE6的回到顶部组件
Oct 10 Javascript
用jQuery旋转插件jqueryrotate制作转盘抽奖
Feb 10 Javascript
js实现动态显示时间效果
Mar 06 Javascript
原生JS实现$.param() 函数的方法
Aug 10 Javascript
微信小程序下拉框组件使用方法详解
Dec 28 Javascript
详解vue-router的Import异步加载模块问题的解决方案
May 13 Javascript
vue实现虚拟列表功能的代码
Jul 28 Javascript
浅谈vue中resetFields()使用注意事项
Aug 12 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
php桌面中心(三) 修改数据库
2007/03/11 PHP
详解PHP中的null合并运算符
2015/12/30 PHP
php解决和避免form表单重复提交的几种方法
2016/08/31 PHP
利用php抓取蜘蛛爬虫痕迹的示例代码
2016/09/30 PHP
PHP多种序列化/反序列化的方法详解
2017/06/23 PHP
类似框架的js代码
2006/11/09 Javascript
在js文件中写el表达式取不到值的原因及解决方法
2013/12/23 Javascript
jquery下拉select控件操作方法分享(jquery操作select)
2014/03/25 Javascript
node.js中的http.response.setHeader方法使用说明
2014/12/14 Javascript
自定义刻度jQuery进度条及插件
2015/09/02 Javascript
简单实现node.js图片上传
2016/12/18 Javascript
移动端手指放大缩小插件与js源码
2017/05/22 Javascript
vue-cli3.0使用及部分配置详解
2018/08/29 Javascript
Bootbox将后台JSON数据填充Form表单的实例代码
2018/09/10 Javascript
fetch 如何实现请求数据
2018/12/20 Javascript
记录vue项目中遇到的一点小问题
2019/05/14 Javascript
Vue监听页面刷新和关闭功能
2019/06/20 Javascript
Vue中登录验证成功后保存token,并每次请求携带并验证token操作
2020/09/08 Javascript
[01:15:18]2014 DOTA2国际邀请赛中国区预选赛 LGD VS Speed Gaming.cn
2014/05/22 DOTA
[02:27]刀塔重生降临
2015/10/14 DOTA
python实现数据图表
2017/07/29 Python
python实现windows下文件备份脚本
2018/05/27 Python
Python OpenCV处理图像之滤镜和图像运算
2018/07/10 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
使用Pyhton集合set()实现成果查漏的例子
2019/11/24 Python
Python连接字符串过程详解
2020/01/06 Python
Python爬取365好书中小说代码实例
2020/02/28 Python
Python使用Excel将数据写入多个sheet
2020/05/16 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
2020/09/21 Python
python 利用panda 实现列联表(交叉表)
2021/02/06 Python
css3 中实现炫酷的loading效果
2019/04/26 HTML / CSS
二手房购房意向书范本
2014/04/01 职场文书
小学生保护环境倡议书
2014/05/15 职场文书
2014法制宣传日活动总结
2014/07/09 职场文书
2016年大学生实习单位评语
2015/12/01 职场文书
python 实现德洛内三角剖分的操作
2021/04/22 Python