先舉例:數組
function factorial(num) { if (num <= 1) { return num; } else { return num * factorial(num-1); } } //輸出120
//進一步去思考
有名字的函數,且名字不會有變化的狀況下,這樣定義沒有問題。
若名字有變化呢,這裏就須要考慮到 須要 【消除】 這種 【緊密耦合】
function factorial(num)
{
if(num<=1)
{
return 1;
}
else{
return num * arguments.callee(num-1);
}
}
//使用 arguments.callee來解決 註釋:argument是一個很大的對象,每次調用都須要從新建立 會影響瀏覽器的性能 還會影響 閉包
咱們知道arguments.callee是一個指向正在執行的函數的指針 (若不理解arguments能夠看下面的)瀏覽器
function factorial(num) { if (num <= 1) { return 1; } else { return num * arguments.callee(num - 1); } } var trueFactorial = factorial; alert(trueFactorial(5)); //120
//註釋:能夠在此處 中 的瀏覽器調試 看 factorial對象 factorial = function () { return 0; }
//註釋:能夠在此處中 的瀏覽器調試 看 trueFactorial 和 factorial對象 alert(trueFactorial(5));// 120 若是沒有使用arguments.callee,將返回0 function mm() { alert(factorial(5)); //0 alert(trueFactorial(5));//120 }
思考:arguments.callee指向arguments對象的擁有函數引用,當把factorial函數的引用賦給trueFactorial後,arguments對象的擁有函數變成了tureFactorial
什麼是arguments ?閉包
arguments是類數組對象,和數組有不少共性。函數
function showargs(){
console.log(arguments)
}
showargs(1,2,3,4);
//獲得的結果如圖
從圖片來看
arguments對象的 ==proto==是指向的object,說明了是一個類數組對象
ES4添加了嚴格模式,在嚴格模式中禁止不使用var來直接聲明一個全局變量,並且arguments也被禁用了性能
回到正題,上面講述了遞歸時的解耦,經過使用arguments.callee來解決,可是在嚴格模式下是不能訪問arguments.callee,那此時有沒有解決方案呢?spa
//能夠經過命名函數表達式來達成相同的結果 var factorial=(function f(num){ if(num<=1){ return 1; } else { return num* f(num-1) } })