arguments.callee的用法 javascript 鏈式寫法
昨天瞭解了一下javascript 鏈式寫法 發現一個特別的方式,
這個寫法也非常優雅,不知會不會影響效能 //arguments.callee 函式自身 var test = (function(x){ console.log(x); return arguments.callee; } )(); test(1)(2)(3);
現在來了解了解arguments.callee,這個物件吧
arguments 的主要用途是儲存函式引數, 但這個物件還有一個名叫 callee 的屬性,返回正被執行的 Function 物件,也就是所指定的 Function 物件的正文,這有利於匿名函式的遞迴或者保證函式的封裝性。
請看下面這個非常經典的階乘函式
function factorial(num){ if (num <=1) { return 1; } else { return num * factorial(num-1) } }
定義階乘函式一般都要用到遞迴演算法;如上面的程式碼所示,在函式有名字,而且名字以後也不會變的情況下,這樣定義沒有問題。
但問題是這個函式的執行與函式名 factorial 緊緊耦合在了一起。為了消除這種緊密耦合的現象,可以像下面這樣使用 arguments.callee
function factorial(num){ if (num <=1) { return 1; } else { return num * arguments.callee(num-1); } }
在這個重寫後的 factorial()函式的函式體內,沒有再引用函式名 factorial。這樣,無論引用函式時使用的是什麼名字,都可以保證正常完成遞迴呼叫。例如
function factorial(num){ if(num <= 1){return 1; }else{ return num * arguments.callee(num-1); } } var trueFactorial = factorial; alert(trueFactorial(5)); //120 factorial = function() { return 0; } alert(trueFactorial(5));// 120 如果沒有使用arguments.callee,將返回0 //因為js中函式沒有過載,所以如果遞迴呼叫時使用函式名,則執行最後一個該函式名的函式,即返回0
在此,變數 trueFactorial 獲得了 factorial 的值,實際上是在另一個位置上儲存了一個函式的指標。然後,我們又將一個簡單地返回 0的函式賦值給 factorial 變數。如果像原來的 factorial() 那樣不使用 arguments.callee,呼叫 trueFactorial()就會返回 0。可是,在解除了函式體內的程式碼與函式名的耦合狀態之後,trueFactorial()仍然能夠正常地計算階乘;至於factorial(),它現在只是一個返回 0的函式。
來看看看開頭提到的匿名函式的遞迴:
var num = (function(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); } })(5); alert(num); //結果為120
昨天提到的arguments.callee效能問題
現在已經不推薦使用arguments.callee();
原因:訪問 arguments 是個很昂貴的操作,因為它是個很大的物件,每次遞迴呼叫時都需要重新建立。影響現代瀏覽器的效能,還會影響閉包。
不能用怎麼辦?
遞迴時用到arguments.callee()是常見的事情,比如
一道面試題。接受引數n=5,不用for迴圈輸出陣列【1,2,3,4,5】
這是用遞迴的思路,配合arguments.callee,程式碼如下
function show(n) { var arr = []; return (function () { arr.unshift(n); n--; if (n != 0) { arguments.callee(); } return arr; })() } show(5)//[1,2,3,4,5]
現在arguments.callee 被棄用了。怎麼辦,其實很簡單,給內部函式一個名字即可(當函式被呼叫時,它的arguments.callee物件就會指向自身,也就是一個對自己的引用。)
function show(n) { var arr = []; return (function fn() { arr.unshift(n); n--; if (n != 0) { fn(); } return arr; })() } show(5)//[1,2,3,4,5]
上面斐波那契那個怎麼改
轉自:https://blog.csdn.net/u013451157/article/details/78686881