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种情况。
- 从n-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