標籤:使用 模式 class 遞迴 適合 script 新手 運算式 訪問
JavaScript遞迴是除了閉包以外,函數的又一特色呢.很多開發新手都很難理解遞迴的原理,我在此總結出自己對遞迴的理解.
所謂遞迴,可以這樣理解,就是一個函數在自身的局部環境裡通過自身函數名又調用,如此反覆,直到條件不滿足,返回最終結果的一種情形.最簡單的一個範例程式碼如下:
function fn(a){ return a <= 1 ? a = 1 : a * fn(a - 1); }
這也是一個最經典的遞迴階乘函數了,雖然這行代碼錶面上看起來沒什麼問題,但在執行如下代碼,則會出現錯誤.
var otherfn = fn;fn = null;otherfn(5);//出錯,fn is not a function
以上將定義的遞迴階乘函數fn()儲存在變數otherfn中,然後將fn()函數設定為null,也就是說,這樣就斷掉了對原始函數fn()的引用,因此在調用otherfn()函數時候就會報錯.畢竟調用otherfn()實際上就相當於是調用fn()函數,而fn()函數已經被解除了引用,所以自然會報一個fn 不是一個函數的錯誤呢.
那麼,有沒有辦法解決呢?
JavaScript的arguments.callee就可以解決這個問題.argumens.callee實際上就是指向一個函數的指標,因此,只要將以上代碼修改成如下所示:
function fn(a){ return a <= 1 ? a = 1 : a * arguments.callee(a - 1);}
這樣,通過arguments.callee代替了函數名fn,就保證了引用不會被解除,因此無論怎麼調用該函數就不會出問題了.
因此,在編寫遞迴函式時,使用arguments.callee總是比直接用函數名更好一點.
不過,使用arguments.callee有個缺點,那就是在strict 模式下,是無非訪問arguments.callee的,因此就需要使用命名函數運算式來達到與這個指標帶來的效果呢.代碼如下:
var fn = (function f(a){ return a <= 1 ? a = 1 : a * f(a - 1);});
以上代碼建立了一個命名為f的函數運算式,然後將它賦值給一個fn變數.因此即便把這個函數運算式賦值給另一個變數,這個函數也仍然可以正常調用.而且這種做法不僅適合非strict 模式,也同樣適合strict 模式.
JavaScript遞迴原理