JavaScript遞歸函數
1.遞歸定義優化
遞歸簡而言之就是一個函數調用自己或者兩個函數相互調用,咱們只討論第一種狀況,須要注意的是, 遞歸是一個比較難以理解的概念,看不懂, 不理解, 太正常了,這須要時間來, 慢慢搞懂它spa
注意:接下來的例子都只是例子而已, 實際不會這麼寫代碼,遞歸有適用的場景, 但不會用來求階乘這樣的事情,只是爲了簡化描述才用了這個例子指針
(1)遞歸求階乘code
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)遞歸求斐波那契數blog
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級樓梯,每次能夠走一步或兩步,求一共多少種走法,思路:ip
要想走到N(N=10)級,能夠分爲2種狀況。it
那麼對於n-2和n-1的狀況也是各自分爲兩種,以此類推。io
那麼走法的和就是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