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 相关文章推荐
jquery zTree异步加载简单实例分享
Feb 05 Javascript
JavaScript实现跨浏览器的添加及删除事件绑定函数实例
Aug 04 Javascript
AngularJS过滤器filter用法实例分析
Nov 04 Javascript
jQuery实现三级联动效果
Mar 02 Javascript
解决React Native端口号修改的方法
Jul 28 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
Aug 17 jQuery
parabola.js抛物线与加入购物车效果的示例代码
Oct 25 Javascript
关于vue单文件中引用路径的处理方法
Jan 08 Javascript
浅谈用Webpack路径压缩图片上传尺寸获取的问题
Feb 22 Javascript
layUI使用layer.open,在content打开数据表格,获取值并返回的方法
Sep 26 Javascript
解决vue项目input输入框双向绑定数据不实时生效问题
Aug 05 Javascript
vue完美实现el-table列宽自适应
May 08 Vue.js
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合并数组array_merge函数运算符加号与的区别
2008/10/31 PHP
php上的memcache和memcached两个pecl库
2010/03/29 PHP
ThinkPHP实现带验证码的文件上传功能实例
2014/11/01 PHP
php获取系统变量方法小结
2015/05/29 PHP
php过滤所有的空白字符(空格、全角空格、换行等)
2015/10/27 PHP
PHP基于GD库的图像处理方法小结
2016/09/27 PHP
PHP对象相关知识总结
2017/04/09 PHP
PHP设计模式之注册树模式分析
2018/01/26 PHP
Thinkphp5.0 框架使用模型Model添加、更新、删除数据操作详解
2019/10/11 PHP
JavaScript的变量作用域深入理解
2009/10/25 Javascript
jquery ajax提交整个表单元素的快捷办法
2013/03/27 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
2016/12/02 Javascript
解析ajaxFileUpload 异步上传文件简单使用
2016/12/30 Javascript
详解angularJs中自定义directive的数据交互
2017/01/13 Javascript
Nodejs 发送Post请求功能(发短信验证码例子)
2017/02/09 NodeJs
Bootstrap表格制作代码
2017/03/17 Javascript
AngularJS动态绑定ng-options的ng-model实例代码
2017/06/21 Javascript
JSONP原理及应用实例详解
2018/09/13 Javascript
nodejs中函数的调用实例详解
2018/10/31 NodeJs
在vue+element ui框架里实现lodash的debounce防抖
2019/11/13 Javascript
JavaScript 实现轮播图特效的示例
2020/11/05 Javascript
swiperjs实现导航与tab页的联动
2020/12/13 Javascript
python快速排序代码实例
2013/11/21 Python
python小技巧之批量抓取美女图片
2014/06/06 Python
Python中使用strip()方法删除字符串中空格的教程
2015/05/20 Python
pycharm 将django中多个app放到同个文件夹apps的处理方法
2018/05/30 Python
django-crontab 定时执行任务方法的实现
2019/09/06 Python
flask框架渲染Jinja模板与传入模板变量操作详解
2020/01/25 Python
Python通过Pillow实现图片对比
2020/04/29 Python
HTML5印章绘制电子签章图片(中文英文椭圆章、中文英文椭圆印章)
2019/06/03 HTML / CSS
详解淘宝H5 sign加密算法
2020/08/25 HTML / CSS
写好求职应聘自荐信的三部曲
2013/09/21 职场文书
业务员岗位职责
2013/11/16 职场文书
人事专员的职责
2014/02/26 职场文书
产品质量承诺书范文
2014/03/27 职场文书
Nginx报错104:Connection reset by peer问题的解决及分析
2022/07/23 Servers