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动画特效和css打造的侧边弹出垂直导航
Apr 04 Javascript
javascript使用正则表达式实现去掉空格之后的字符
Feb 15 Javascript
JQuery选中checkbox方法代码实例(全选、反选、全不选)
Apr 27 Javascript
Bootstrap3 Grid system原理及应用详解
Sep 30 Javascript
Jquery鼠标放上去显示全名的实现方法
Feb 06 Javascript
JS去除字符串中空格的方法
Feb 14 Javascript
ionic环境配置及问题详解
Jun 27 Javascript
webpack+vuex+axios 跨域请求数据的示例代码
Mar 06 Javascript
bootstrap里bootstrap动态加载下拉框的实例讲解
Aug 10 Javascript
代码分析vue中如何配置less
Sep 28 Javascript
vue.js 2.0实现简单分页效果
Jul 29 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
Nov 11 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自动更新新闻DIY
2006/10/09 PHP
PHP 多维数组排序实现代码
2009/08/05 PHP
详谈PHP编码转换问题
2015/07/28 PHP
PHP 前加at符合@的作用解析
2015/07/31 PHP
thinkPHP实现的联动菜单功能详解
2017/05/05 PHP
Laravel实现通过blade模板引擎渲染视图
2019/10/25 PHP
jquery 表单进行客户端验证demo
2009/08/24 Javascript
理解 JavaScript 预解析
2009/10/25 Javascript
JS 模态对话框和非模态对话框操作技巧汇总
2013/04/15 Javascript
IE下JS读取xml文件示例代码
2013/08/05 Javascript
使用 TypeScript 重新编写的 JavaScript 坦克大战游戏代码
2015/04/07 Javascript
JavaScript Promise 用法
2016/06/14 Javascript
jQuery树形控件zTree使用小结
2016/08/02 Javascript
如何提高javascript加载速度
2016/12/26 Javascript
JS分页的实现(同步与异步)
2017/09/16 Javascript
vue中vee validate表单校验的几种基本使用
2018/06/25 Javascript
vue select 获取value和lable操作
2020/08/28 Javascript
antd vue table跨行合并单元格,并且自定义内容实例
2020/10/28 Javascript
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
Python之Scrapy爬虫框架安装及使用详解
2017/11/16 Python
解决pandas 作图无法显示中文的问题
2018/05/24 Python
Python for循环生成列表的实例
2018/06/15 Python
解决Python pandas df 写入excel 出现的问题
2018/07/04 Python
简单了解python的break、continue、pass
2019/07/08 Python
Django调用支付宝接口代码实例详解
2020/04/04 Python
浅析python 动态库m.so.1.0错误问题
2020/05/09 Python
html5 视频播放解决方案
2016/11/06 HTML / CSS
HTML5实现视频弹幕功能
2019/08/09 HTML / CSS
EntityManager都有哪些方法
2013/11/01 面试题
房地产资料员岗位职责
2014/07/02 职场文书
公司领导九九重阳节发言稿2014
2014/09/25 职场文书
简易离婚协议书范本
2014/10/24 职场文书
2014年政协委员工作总结
2014/12/01 职场文书
关于公司年会的开幕词
2016/03/04 职场文书
Redis模仿手机验证码发送的实现示例
2021/11/02 Redis
SQLyog的下载、安装、破解、配置教程(MySQL可视化工具安装)
2022/09/23 MySQL