JS尾递归的实现方法及代码优化技巧
本文实例讲述了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数据结构与算法技巧总结》、《JavaScript数学运算用法总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》
希望本文所述对大家JavaScript程序设计有所帮助。
- 区块链入门教程
- python爬虫beautifulsoup4系列2
- python爬虫beautifulsoup4系列3
- 多元回归模型
- C++ STL之min_element()与max_element()(取容器中的最大最小值)
- RESTful API 设计最佳实践
- python爬虫beautifulsoup4系列4-子节点
- 元胞自动机实现多数分类算法
- 51Nod 1289 大鱼吃小鱼(模拟,经典好题)
- 用Metaclass实现一个精简的ORM框架
- HDU 2504 又见GCD(最大公约数与最小公倍数变形题)
- Selenium2+python自动化63-二次封装(click/send_kesy)
- Selenium2+python自动化65-js定位几种方法总结
- HDU 2502 月之数(二进制,规律)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 安装vcs
- Mercari数据集——机器学习&深度学习视角
- 查找重复姓名的sql语句
- nginx如何限制并发连接请求数?
- RTSP协议视频平台EasyNVR证书配置界面上传文件地址自动填写错误怎么处理?
- 开发RTSP/RTMP/GB28181/海康SDK/EHome视频融合平台EasyCVR,使用vue-cli3项目搭建多页面模式的方法
- 互联网视频直播&点播平台RTMP推流组件EasyRTMP在弱网环境下推流稳定吗?会不会有推流失败的问题?
- 安防融合视频云服务EasyCVR集成海康EHome协议实现设备录像回看返回会话ID为-1是什么情况?
- git .gitignore 忽略规则的匹配语法
- vue 初始化高德地图
- js -- 判断数组是否为空?
- 手机没网了,却还能支付,这是什么原理?
- grub异常
- 34.Python字符串替换方法translate
- 35.Python字符串格式运算符%