函數聲明語句:function f(x){},其中x就是參數。
參數分為兩種:
- 形參(parameter):函數定義時圓括號里的數據。
- 實參(arguments);函數調用時,傳給函數作為參數的數據。
EMCAScript規定在調用函數時,可傳入任意數量,任意類型的參數,可以不跟函數定義時傳入的形參數量相對應。為什么會這樣呢?
原因就是,EMACAScript中的參數在內部是用一個數組來表示的,函數接收的始終是這個數組,而不關心包含哪些參數。而且,在函數體內也可以通過arguments這個對象來訪問這個參數數組,從而獲取傳遞給函數的每一個參數。(arguments就是一個對象--函數的一個內部對象,和this一樣。)因此arguments看起來就像一個類數組了。可以用arguments[n]來訪問各個位置的元素了.
要了解arguments對象,就需要先函數的內部屬性。
函數內部,有兩個特殊對象:arguments 和 this。
arguments是一個類數組對象,包含着傳入函數中的所有參數。該對象有一個屬性callee,該屬性是一個指針,指向擁有這個arguments對象的函數。經典例子是階乘函數:
1 function factorial(num){ 2 if(num <= 1){ 3 return 1; 4 }else{ 5 return num * factorial(num-1); 6 } 7 } 8 9 //修改一下,消除函數的執行與函數名緊密的耦合在一起, 10 function factorial(num){ 11 if(num <= 1){ 12 return 1; 13 }else { 14 return num * arguments.callee(num-1); 15 } 16 } 17 18 //修改后函數名factorial就沒出現在函數體內部,因此,無論引用函數時使用什么名字,都能保證正常完成遞歸。 19 //例如 20 var trueFactorial = factorial; 21 factorial = function(){ 22 return 0; 23 }; 24 alert(trueFactorial(5)); //120 25 alert(factorial(5)); //0 26 //在上面的例子里,變量trueFactorial 獲得了factorial的值,實際上就是在另一個位置上保存了一個指向函數的指針,就是讓另一個變量也可以應用該函數,正如在函數定義時說的,函數名是一個指向函數的指針,函數體本身存在那里,通過函數名可以訪問罷了,二者相互獨立,又存在某種聯系。 27 //然后將一個返回0的新函數賦給變量factorial。如果在函數體內有變量名factorial,如第一個例子,則trueFactorial()就會返回0.但改成arguments.callee后就能夠讓trueFactorial正常計算。
與callee屬性對應的就是caller屬性,arguments對象也擁有caller屬性,即:arguments.caller。但在嚴格模式下訪問它會報錯,而在非嚴格模式下這個屬性始終是undefined。該屬性主要就是為了分清arguments.caller和函數的caller屬性。函數的caller屬性指向調用該函數的外部函數。
arguments.callee.caller 和函數的caller屬性等效。
function outer(){ inner(); } function inner(){ alert(inner.caller); //等價於alert(arguments.callee.caller); } outer(); //返回outer函數的代碼
arguments還有一個length屬性,返回傳入參數的個數。和Array.length類似。
前面說的在函數內部可以通過arguments對象訪問傳入的參數。那也可以和命名參數一起在函數內部使用:
function doAdd(num1,num2){ if(arguments.length == 1){ alert(num1 + 10); }else if(arguments.length == 2){ alert(arguemnts[0] + num2); } }
還有一點。arguments的值永遠與對應的命名參數保持同步:
function doAdd(num1,num2){ arguments[1] = 10; alert(arguments[0] + num2); }
什么意思呢?就是每次執行這個函數時,里面的arguments[1]都會被設成10,對應的num2也會跟着變着10。
最后一點:沒有傳遞值的命名參數將自動被賦予undefined,就像變量沒有初始化一樣。
關於函數定義時的參數,其實就像在函數內部定義的變量一樣,只不過不用在顯性的使用var來進行定義。