函數的內部屬性主要有三個:arguments, this, caller
。其中this
在簡析JavaScript中的this關鍵字中探討的已經比較清楚了,這裏來講下arguments
和caller
。javascript
看下面的代碼:java
function sayHello(){ console.log(arguments[0], arguments[1], arguments[2]); } sayHello('Bob', 'Jack', 'Rose');// Bob Jack Rose
如代碼所示,聲明sayHello
時沒有顯式地聲明參數,可是在函數內部依然能夠經過arguments
訪問傳遞給函數的參數。arguments
是一個類數組對象,包含着傳入函數中的全部參數。數組
arguments
除了能夠保存參數之外,它還有一個名叫callee
的屬性,該屬性指向包含arguments
的函數,以下代碼所示:函數
function sayHello(){ console.log(arguments.callee); } sayHello(); /* 控制檯輸出: ƒ sayHello(){ console.log(arguments.callee); } */
那麼將函數的引用保存在arguments.callee
中有什麼用處呢?下面是一個使用示例:this
//階乘函數 function factorial(num){ if(num <= 1){ return 1; }else{ return num * factorial(num - 1); } } console.log(factorial(4));//24
這種寫法在函數有名字,並且名字之後也不會變的狀況下是沒有問題的。可是函數的執行與函數名factorial
牢牢耦合在了一塊兒,當函數名發生變化時,調用就出現了問題:.net
var trueFactorial = factorial; factorial = null; console.log(trueFactorial(4));//Uncaught TypeError: factorial is not a function
使用arguments.callee
能夠達到解耦的目的:code
function factorial(num){ if(num <= 1){ return 1; }else{ return num * arguments.callee(num - 1); } } var trueFactorial = factorial; factorial = null; console.log(trueFactorial(4));// 24
如代碼所示,不管未來函數名如何變化,始終都能保證正確的執行結果。對象
從字面意思理解,爲調用者。這個屬性保存着當前函數的調用函數,若是是在全局做用域中調用,它的值爲null
。來看下面的例子:blog
function inner(){ console.log(inner.caller); } function outer(){ inner(); } inner();// null outer();// 結果以下: /* ƒ outer(){ inner(); } */
如代碼所示,在全局做用域中調用時結果爲null
,在outer
中調用時結果爲outer
。一樣,爲了解耦合,也能夠將inner
改寫以下:ip
function inner(){ console.log(arguments.callee.caller); }
須要注意的是嚴格模式是不支持arguments
和caller
屬性的。