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 函数调用模式小结
Dec 26 Javascript
jquery 事件冒泡的介绍以及如何阻止事件冒泡
Dec 25 Javascript
jQuery移动端图片上传组件
Jun 12 Javascript
JS验证input输入框(字母,数字,符号,中文)
Mar 23 Javascript
bootstrap日期控件问题(双日期、清空等问题解决)
Apr 19 Javascript
vue proxyTable 接口跨域请求调试的示例
Sep 12 Javascript
vue的toast弹窗组件实例详解
May 14 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
May 07 Javascript
微信小程序如何刷新当前界面的实现方法
Jun 07 Javascript
echarts.js 动态生成多个图表 使用vue封装组件操作
Jul 19 Javascript
ant-design表单处理和常用方法及自定义验证操作
Oct 27 Javascript
javascript代码简写的几种常用方式汇总
Aug 23 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
深入了解php4(2)--重访过去
2006/10/09 PHP
使用php测试硬盘写入速度示例
2014/01/27 PHP
你可能不知道PHP get_meta_tags()函数
2014/05/12 PHP
CodeIgniter框架URL路由总结
2014/09/03 PHP
Symfony实现行为和模板中取得request参数的方法
2016/03/17 PHP
PHP查询大量数据内存耗尽问题的解决方法
2016/10/28 PHP
Laravel 框架返回状态拦截代码
2019/10/18 PHP
自适应图片大小的弹出窗口
2006/07/27 Javascript
jquery如何实现在加载完iframe的内容后再进行操作
2013/09/10 Javascript
在父页面调用子页面的JS方法
2013/09/29 Javascript
JQuery删除DOM节点的方法
2015/06/11 Javascript
jquery实现轮播图效果
2017/02/13 Javascript
深入理解基于vue-cli的vuex配置
2017/07/24 Javascript
Vue中计算属性computed的示例解读
2017/07/26 Javascript
bootstrap 通过加减按钮实现输入框组功能
2017/11/15 Javascript
浅谈一个webpack构建速度优化误区
2019/06/24 Javascript
记录vue做微信自定义分享的一些问题
2019/09/12 Javascript
Vue项目打包部署到iis服务器的配置方法
2019/10/14 Javascript
Vue如何基于vue-i18n实现多国语言兼容
2020/07/17 Javascript
[01:20]2018DOTA2亚洲邀请赛总决赛战队Mineski晋级之路
2018/04/07 DOTA
python用模块zlib压缩与解压字符串和文件的方法
2016/12/16 Python
python批量赋值操作实例
2018/10/22 Python
Python基于WordCloud制作词云图
2019/11/29 Python
浅谈Pytorch torch.optim优化器个性化的使用
2020/02/20 Python
pytorch中的inference使用实例
2020/02/20 Python
Python matplotlib可视化实例解析
2020/06/01 Python
python 实现音频叠加的示例
2020/10/29 Python
J2EE的优越性主要表现在哪些方面
2016/03/28 面试题
传播学毕业生求职信
2013/10/11 职场文书
大学生活学习的自我评价
2013/12/03 职场文书
创业计划实施的7大步骤
2014/02/05 职场文书
检查接待方案
2014/02/27 职场文书
大学生入党推荐书范文
2014/05/17 职场文书
法人委托书范本格式
2014/09/15 职场文书
毕业生就业推荐表导师评语
2014/12/31 职场文书
私人贷款担保书该怎么写呢?
2019/07/02 职场文书