遞歸函數大家都應該比較熟吧?那麼,如何在JavaScript中書寫一個完美的遞歸函數呢?且聽我娓娓道來。
寫的時候,查了一下維基百科對遞歸函數的定義,恕我愚鈍,簡直太深奧了!所以,我還是簡單的說說我對遞歸函數的理解吧。遞歸函數,說白了就是在函數內部引用函數自身,最終到給定的遞歸結束條件時回溯。當然,你也可以不給定結束條件,死了別掛我~(╯﹏╰)~
現在,一步一步,摩擦摩擦,在皎潔的編輯器上,來開始使用javascript寫遞歸函數吧!
function fun(num){
if(num <= 1){
return 1;
} else{
return num * fun(--num);
}
}
好了,不錯,一個堪稱經典的遞歸求階乘的函數誕生了。事情肯定不會這麼順利,一定是個圈套。我們來如下調用以下看看會怎麼樣?
var test = fun;
fun = null;
console.log(test(7));
呵呵,居然報錯了
Uncaught TypeError: object is not a function
嗯,報了類型錯誤。。。
回過頭去看看我們是如何調用的。發現問題了吧!我們把fun賦給了test,然後把fun給回收掉了。為什麼會出錯呢?因為像function這種賦值其實是引用傳遞,只是把指向函數的指針(這裡說地址也行)賦給test了。但我們把fun賦值為null的時候,函數都已經被回收了,拿什麼來執行?知道問題所在了,我決定換種方式來定義:
function fun(num){
if(num <= 1){
return 1;
} else{
return num * arguments.callee(--num);
}
}
然後測試一下:
var test = fun;
fun = null;
console.log(test(7));
OK,測試通過!
但是在某一天,當我實際碼代碼的時候,問題又出現了。什麼問題呢?我們來看一下:
Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
╮(╯▽╰)╭哎!可憐啊!因為我使用了"use strict"!嚴格模式下是不允許的。。。
好吧!繼續想辦法!既然不能使用arguments.callee(),那還是想想其他的方式吧。
看下面的代碼:
var fun = (function f(num){
if(num <= 1){
return 1;
} else{
return num * f(--num);
}
});
然後我測試了以下,神奇的通過了,暫時沒有發現任何問題!
為什麼呢?因為我們使用了“()”,巧妙地使用命名函數表達式來達到了同樣的效果。
《JavaScript高級程序設計(第三版)》 http://www.linuxidc.com/Linux/2014-09/107426.htm