ES6 入门系列 (三) 尾递归
递归我们不陌生,
那什么是尾递归呢?
为什么要用尾递归呢?
尾递归怎么用呢?
带着这三个问题我们来了解它,
我们知道递归非常耗费内存,一不小心就会发生‘栈溢出’, 相信你一定遇到过这个错误: stack overflow,
尾递归就是用来优化递归的这个问题的。
尾递归的定义: 在函数的最后一步返回自身,也就是显示地return自身就称为尾递归。对于尾递归来说,
由于只存在一个调用帧,所以永远不会发生‘栈溢出’。
我们来举例说明尾递归的好处:
- 比如计算n的阶乘, 我们首先想到找规律, n的阶乘等于n* (n-1)的阶乘
- 找出口1的阶乘等于1
- 然后我们就很自然的用递归写出
function jieCheng(n) {
if (n===1) {
return 1
}
return n * jieCheng(n -1);
}
const result = jieCheng(5); console.log(result); //很自然, so easy有木有,
but, 这样我们每递归一次,上一次的调用记录还保存着, 也就是说我们计算n的阶乘最多要保存n个调用记录,复杂度为O(n).
改成尾递归:
function weiJieCheng(n, total=1) {
if (n === 1) {
return total;
}
return weiJieCheng(n-1, n * total);
} console.log(weiJieCheng(5), 'wei'); //
把中间变量改写成函数的参数, 这样就只保存了一个调用记录,复杂度为O(1)。
再用蹦床函数对尾递归进行优化,把递归执行转换成循环执行:
function trampoline(f) {
while(f && f instanceof Function) {
f = f ();
}
}
trampoline(weiJieCheng(5, 1))
ES6 入门系列 (三) 尾递归的更多相关文章
- ES6入门系列三(特性总览下)
0.导言 最近从coffee切换到js,代码量一下子变大了不少,也多了些许陌生感.为了在JS代码中,更合理的使用ES6的新特性,特在此对ES6的特性做一个简单的总览. 1.模块(Module) --C ...
- mybatis入门系列三之类型转换器
mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名, ...
- C# 互操作性入门系列(三):平台调用中的数据封送处理
好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...
- [转]C# 互操作性入门系列(三):平台调用中的数据封送处理
参考网址:https://www.cnblogs.com/FongLuo/p/4512738.html C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列( ...
- ActiveMQ入门系列三:发布/订阅模式
在上一篇<ActiveMQ入门系列二:入门代码实例(点对点模式)>中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub & Sub),详细介绍了点对点 ...
- ES6 入门系列 - 函数的扩展
1函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log( ...
- ES6入门系列四(测试题分析)
0.导言 ES6中新增了不少的新特性,来点测试题热热身.具体题目来源请看:http://perfectionkills.com/javascript-quiz-es6/. 以下将一题一题来解析what ...
- ES6 入门系列 - let 和 const 命令
let命令 基本用法 ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = ; ; } a // ReferenceEr ...
- ES6 入门系列 (一)ES6的前世今生
要学好javascript , ECMAScript标准比什么都强, ESMAScript标准已经用最严谨的语言和最完美的角度展现了语言的实质和特性. 理解语言的本质后,你已经从沙堆里挑出了珍珠,能经 ...
随机推荐
- 李宏毅-Network Compression课程笔记
一.方法总结 Network Pruning Knowledge Distillation Parameter Quantization Architecture Design Dynamic Com ...
- socket_http
socket_http import socket from urllib.parse import urlparse import time def get_url(url): # 通过socket ...
- <console>:14: error: not found: value spark import spark.implicits.
启动 ./spark-shell 出现问题 启动 hadoop, 并创建,解决 hadoop fs -mkdir /directory 解决了
- hive数据库从文件插入数据得到结果NULL?
今天第一次接触hive这个东东,跟着教程走,当把本地文件的数据装载到新建的hive的表中时,得到的结果是NULL,如图: 也不知道为什么,初次接触,对它的这个构造还不是很熟悉,看一下建表语句: 解决: ...
- java数组的N种打印方式
int[] array = {1,2,3,4,5}; (1)传统的for循环方式 ;i<array.length;i++) { System.out.println(a[i]); } (2)fo ...
- [RN] 使用 Genymotion 导致 ” Genymotion 已连接,但无法访问互联网 “ 的错误
使用 Genymotion 导致 Genymotion 已连接,但无法访问互联网 的错误 先把要点 放前面: 网络二 一定要设置 桥接模式 网上很多文章都是设置为 NAT,笔者均失败! 笔者使用的An ...
- how to design AWS SQS?
遇到这么一题system design,怎么做? 几个月以前,有同事提出要用Webapi代替现有的WCF,当时我投的反对票.而且我给了很充分的理由,不仅仅是时间不足,人手不够,更重要的是这个变化太大, ...
- 10.24考试题解qwq
考点难度都很合适的一套题目,大概在day1到day2之前 T1 猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有N个苹果,每个苹果有一个编号,分别为0~N-1,它们之间由N-1个树枝相连,猴猴可 ...
- CSP2019 树的重心 题解
本题当然可以通过大力讨论每棵子树的size的大小关系,然后用各种数据结构暴力维护.但是我更倾向于用一种更为性质的做法. 首先讲一下我在考场上想到的做法(没写).就是考虑换根,在换根的过程中计算每一条边 ...
- Vue组件的操作-自定义组件,动态组件,递归组件
作者 | Jeskson 来源 | 达达前端小酒馆 v-model双向绑定 创建双向数据绑定,v-model指令用来在input,select,checkbox,radio等表单控件.v-model指 ...