arguments.callee

在函數內部,有兩個特殊的對象:arguments 和 this。其中, arguments 的主要用途是保存函數參數, 但這個對象還有一個名叫 callee 的屬性,該屬性是一個指針,指向擁有這個 arguments 對象的函數。 請看下面這個很是經典的階乘函數javascript

function factorial(num){    
   if (num <=1) {         
      return 1;     
   } else {         
   return num * factorial(num-1)     
   } 
}  

定義階乘函數通常都要用到遞歸算法;如上面的代碼所示,在函數有名字,並且名字之後也不會變 的狀況下,這樣定義沒有問題。但問題是這個函數的執行與函數名 factorial 牢牢耦合在了一塊兒。爲 了消除這種緊密耦合的現象,能夠像下面這樣使用 arguments.calleejava

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

在此,變量 trueFactorial 得到了 factorial 的值,其實是在另外一個位置上保存了一個函數 的指針。而後,咱們又將一個簡單地返回 0的函數賦值給 factorial 變量。若是像原來的 factorial() 那樣不使用 arguments.callee,調用 trueFactorial()就會返回 0。但是,在解除了函數體內的代 碼與函數名的耦合狀態以後,trueFactorial()仍然可以正常地計算階乘;至於 factorial(),它現 在只是一個返回 0的函數。 算法

 

參考自js高程第三版數組

 

2017/4/5號更新瀏覽器

如今已經不推薦使用arguments.callee();閉包

緣由:訪問 arguments 是個很昂貴的操做,由於它是個很大的對象,每次遞歸調用時都須要從新建立。影響現代瀏覽器的性能,還會影響閉包。函數

 

不能用怎麼辦?性能

像第三段中的例子,重寫 factorial()方法致使trueFactorial()結果不在預期。是爲了演示而作的。平時寫代碼應該避免。this

遞歸時用到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 被棄用了。怎麼辦,其實很簡單,給內部函數一個名字便可

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]
相關文章
相關標籤/搜索