JavaScript中的递归

JavaScript递归

1.递归定义

递归简而言之就是一个函数调用本身或者两个函数相互调用,我们只讨论第一种情况,需要注意的是, 递归是一个比较难以理解的概念,看不懂, 不理解, 太正常了,这需要时间来, 慢慢搞懂它

注意:接下来的例子都只是例子而已, 实际不会这么写代码,递归有适用的场景, 但不会用来求阶乘这样的事情,只是为了简化描述才用了这个例子

(1)递归求阶乘

 1 var fac = function(n) {
 2     // 如果 n 是 0 则返回 1
 3     // 这是递归终止的条件, 必须要有, 否则无限递归了
 4     if(n == 0) {
 5         return 1
 6     } else {
 7         // 如果 n 不为 0, 返回 n * fac(n-1)
 8         // 这时候 n 是已知的, fac(n-1) 需要计算
 9         // 于是代码进入下一重世界开始计算
10         return n * fac(n-1)
11     }
12 }
13 
14 console.log('递归阶乘', fac(5))  // 120

(2)递归求斐波那契数

 1 var fib = function(n) {
 2     // 如果 n 是 1 或者 2 则返回 1 作为结果
 3     // 这是递归终止的条件, 必须要有, 否则无限递归了
 4     if(n == 1 || n == 2) {
 5         return 1
 6     } else {
 7         // 如果 n 不为 1 和 2, 返回 fib(n-2) + fib(n-1)
 8         // 这时候 fib(n-2) fib(n-1) 需要计算
 9         // 于是代码进入下一重世界开始计算
10         return fib(n-2) + fib(n-1)
11     }
12 }
13 
14 console.log('递归 fib: ', fib(6))  // 8

2.经典递归

一共10级楼梯,每次可以走一步或两步,求一共多少种走法,思路:

要想走到N(N=10)级,可以分为2种情况。

  1. 从n-2级迈两步
  2. 从n-1级迈一步

那么对于n-2和n-1的情况也是各自分为两种,以此类推。

那么走法的和就是n-2的走法和n-1的走法之和。

那么递归到最基本的(当前人在第0阶台阶)

第0阶台阶:0

第1阶台阶:1

第2阶台阶:2(1+1或者2)

得到公式,也就是斐波那契数列。

 1 var fib = function (n){
 2     if(n == 1){
 3         return 1;
 4     }
 5     else if(n==2){
 6         return 2;
 7     }
 8     else if(n>2){
 9         return fib(n-1) + fib(n-2);
10     }
11 }
12 
13 console.log(fib(10));

3.JavaScript递归中的注意问题

当使用函数表达式来递归时可能会导致一些问题:

 1 // 函数表达式与递归:
 2 var func = function (num) {
 3     if (num<=1){
 4         return 1;
 5     }      
 6     else{
 7         return num * func(num-1);
 8     }
 9 };
10 var anotherFunc = func;
11 func = null;
12 console.log(anotherFunc(4));  // 报错!

出错原因:func变量执行上述操作后为空,结果指向原始函数的引用就只剩下一个,但是在接下来的调用anotherFunc中必须执行func,而func已经不是函数了,所以就导致错误出现,在这种情况下使用aruguments.callee可以解决这个问题

aruguments.callee:是一个指向函数的指针,因此可以用它来实现对函数的递归调用

 1 // 函数表达式与递归:
 2 var func = function (num) {
 3     if (num<=1){
 4         return 1;
 5     }      
 6     else{
 7         return num * arguments.callee(num-1);
 8     }
 9 };
10 var anotherFunc = func;
11 func = null;
12 console.log(anotherFunc(4));  // 24

另外arguments.callee可以实现匿名函数的递归调用:

 1 // 匿名函数的递归调用
 2 (
 3     function (count) {
 4         if(count<=3){
 5             console.log(count);
 6             arguments.callee(++count);
 7         }
 8     }
 9 )(0);
10 
11 // 输出结果: 0 1 2 3

4.尾递归

尾递归:是一种在函数的最后执行递归调用语句的特殊形式的递归

尾递归示例:

1 var factorial = function(i, a) {
2     a = a || 1;  // 1是默认值
3     if (i < 2) {
4         return a;
5     }
6         // 返回自身调用的结果 -》 尾递归 -》JavaScript没有对这种递归做优化 
7     return factorial(i - 1, a * i);
8 };
9 document.writeln(factorial(4));  // 24
原文地址:https://www.cnblogs.com/wyb666/p/9335931.html