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 相关文章推荐
js与jquery获取父元素,删除子元素的两种不同方法
Jan 09 Javascript
基于javascript编写简单日历
May 02 Javascript
Bootstrap 组件之按钮(二)
May 11 Javascript
AngularJS实现标签页的两种方式
Sep 05 Javascript
Bootstrap模态框水平垂直居中与增加拖拽功能
Nov 09 Javascript
百度地图JavascriptApi Marker平滑移动及车头指向行径方向
Mar 13 Javascript
浅谈JavaScript中的属性:如何遍历属性
Sep 14 Javascript
静态页面实现 include 引入公用代码的示例
Sep 25 Javascript
ES6 javascript中class静态方法、属性与实例属性用法示例
Oct 30 Javascript
Vue.js 实现微信公众号菜单编辑器功能(二)
May 08 Javascript
JavaScript 斐波那契数列 倒序输出 输出100以内的质数代码实例
Sep 11 Javascript
JS中如何优雅的使用async await详解
Oct 05 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
取得单条网站评论以数组形式进行输出
2014/07/28 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
Yii扩展组件编写方法实例分析
2015/06/29 PHP
php实现html标签闭合检测与修复方法
2015/07/09 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
php对微信支付回调处理的方法
2018/08/23 PHP
基于jquery的超简单上下翻
2010/04/20 Javascript
Firefox中autocomplete="off" 设置不起作用Bug的解决方法
2011/03/25 Javascript
jQuery判断iframe中元素是否存在的方法
2013/05/11 Javascript
JavaScript显示当然日期和时间即年月日星期和时间
2013/10/29 Javascript
使用js实现一个可编辑的select下拉列表
2014/02/20 Javascript
常见浏览器多长时间会提示“脚本运行时间过长”总结
2014/04/29 Javascript
详谈javascript中DOM的基本属性
2015/02/26 Javascript
js验证框架之RealyEasy验证详解
2016/06/08 Javascript
javaScript生成支持中文带logo的二维码(jquery.qrcode.js)
2017/01/03 Javascript
全面解析Node.js 8 重要功能和修复
2017/06/02 Javascript
vue+elementUI 复杂表单的验证、数据提交方案问题
2019/06/24 Javascript
详解vue3中组件的非兼容变更
2021/03/03 Vue.js
python3+PyQt5使用数据库表视图
2018/04/24 Python
Python基础学习之函数方法实例详解
2019/06/18 Python
Python魔法方法 容器部方法详解
2020/01/02 Python
Python写出新冠状病毒确诊人数地图的方法
2020/02/12 Python
浅谈python多线程和多线程变量共享问题介绍
2020/04/17 Python
pycharm 实现本地写代码,服务器运行的操作
2020/06/08 Python
分享PyCharm最新激活码(真永久激活方法)不用每月找安装参数或最新激活码了
2020/12/27 Python
一款纯css3制作的2015年元旦雪人动画特效教程
2014/12/29 HTML / CSS
五个2015 年最佳HTML5 框架
2015/11/11 HTML / CSS
JSF面试题:Jsf中的核心类用那些?有什么作用?LiftCycle六大生命周期是什么?
2014/07/17 面试题
应聘自荐信
2013/12/14 职场文书
计算机相关的自我评价
2014/01/15 职场文书
承诺书的格式范文
2014/03/28 职场文书
与美同行演讲稿
2014/09/13 职场文书
贵阳市党的群众路线教育实践活动党(工)委领导班子整改方案
2014/10/26 职场文书
数学复习课教学反思
2016/02/18 职场文书
Python中OpenCV实现简单车牌字符切割
2021/06/11 Python
关于Spring配置文件加载方式变化引发的异常详解
2022/01/18 Java/Android