先給一個例子,函數的功能是傳回陣列元素的和;
function sumArray(arr) { var sum = 0; for(var i = 0,aLength = arr.length;i < aLength;i++) { sum += arr[i]; } return sum; }
關鍵字function
後面空一格, sumArray
是函數的名字,其命名規範與變數名的命名規範相同:只能有字母、數字、底線和美元符號,不能以數字開頭,不能是關鍵字。
括號中是參數,又叫形式參數,只需要參數名稱就可以。參數可以是0
個、 1
個或多個,彼此之間用,
隔開, {}
中間包含的是函數體。含有一條或多條語句。函數體用來實現函數的功能。
關鍵字return
後面是函數的回傳值,函數也可以沒有回傳值。函數運行完return
這句話這裡就會退出運行, return
下面的語句就不再運行。傳回值即函數的輸出。
用這種方式定義的函數,在函數定義的前面和後面都可以呼叫該函數,只要函數和呼叫函數的語句在一個原始檔裡面就可以了。
用表達式的方式定義函數,就是用賦值表達式把函數賦值給一個變量,這其實就是把函數看成一個變數。這時候函數可以有名字,也可以沒有名字,沒有名字的函數叫做匿名函數。
var funct = function getMax(a,b) { return a>b?a:b; };//注意這後面的分號不能少,因為我們定義的是一個變數!
和用函數語句定義不同的是,只能在函數定義語句之後呼叫函數,且呼叫的時候只能用變數名funct
,不能用函數名getMax
,如:
var funct = function getMax(a,b) { return a>b?a:b; }; console.log(funct(1,2));//輸出2
function
之後直接是參數列表:var funct = function(a,b) { return a>b?a:b; };
這個函數沒有名字,它被賦值給了變數funct
,所以叫匿名函數。同樣,也只能在這一語句之後呼叫該函數。
var funct = function(a,b) { return a>b?a:b; }; console.log(funct(1,2));//輸出2
總結:用表達式定義函數是即拿即用的,定義了就只能在這一語句之後呼叫該函數
在實行四中,我們曾經介紹過物件可以有自己的方法,當然這也是函數。這種函數的呼叫和前面兩關定義的函數有細小的差別。
//函數的定義:求三個數的最大值function max(a,b,c) { if(a > b) { if(a > c) return a; else return c; } else { if(b > c) return b; else return c; } } //呼叫函數var result = max(1,2,3);//result為3 console.log(result);//輸出3
呼叫函數的時候,需要傳入和形參相同個數的的具體值,上面的函數有3
個參數,所以下面呼叫的時候傳入3
個具體的值, 1
傳給參數a
, 2
傳給參數b
, 3
傳給參數c
。函數的回傳值透過賦值符號=
傳給了變數result
。如果函數體內沒有return
關鍵字,將會傳回undefined
。
物件裡定義的函數的呼叫:
var ob = { id:1, getMax:function(a,b) { return a>b?a:b; } }; var result = ob.getMax(2,1);//result值為2 var result1 = ob["getMax"](2,1);//result1的值也是2
與上面的差異是,這裡要定位到函數,需要使用对象名.函数名
或对象名["函数名"]
,其它相同。
在大部分的程式語言裡面,都會對呼叫函數時傳入的實參數和型別進行檢查,而JavaScript
既不檢查實參的型別,也不檢查實參的個數。
JavaScript
中的實參會依序由左至右依序匹配上形參,例如:
function myFunction(a,b,c) { console.log(a); console.log(b); console.log(c); } myFunction(1,2,3);
實參1
傳入形參a
,實參2
傳入形參b
,實參3
傳入形參c
。 當實參個數少於形參時,靠右的形參會被傳入值undefined
。如:
function myFunction(a,b,c) { console.log(a); console.log(b); console.log(c); } myFunction(1,2);
實參1
傳入形參a
,實參2
傳入形參b
, undefined
傳入形參c
。 如果只想給右側的參數傳入數據,可以給前幾個實參傳入undefined
。如:
function myFunction(a,b,c){ console.log(a); console.log(b); console.log(c); } myFunction(undefined,1,2);
上面這兩種做法不夠嚴謹,最佳實踐是為可能被傳入undefined
值的形參設定一個預設值。如:
function getSum(a,b,c) { if(c === undefined) c = 0; console.log(a+b+c); } myFunction(1,2);
JavaScript
一切都是對象,實參也是一個對象,有一個專門的名字arguments
,這個對象可以看成一個數組(類別數組,不是真的數組),實參從左到右分別是arguments[0]、arguments[1]...
, arguments.length
表示實參的個數。
//求參數的和function getSum() { var aLength = arguments.length; var sum = 0; for(var i = 0;i < aLength;i++) { sum += arguments[i]; } return sum; } console.log(getSum(1,2,3,4,5))//輸出15
這裡的形參直接省略,使用arguments[i]
表示。
複雜的函數通常多達十幾個參數,儘管JavaScript
不做參數個數和類型的檢查,但是呼叫時實參的順序不能亂。開發人員需要檢視每一個實參和形參的對應關係,這樣效率很低。一個很好的解決方案是使用物件作為參數,函數會根據物件的屬性名稱操作參數。
function myFunction(obj) { console.log(obj.name); obj.number++; return obj.number; } myObj = {name:"myObj",number:34}; myFunction(myObj);//輸出myObj console.log(myObj.number);//輸出35
一個函數(為方便行文,稱為a
函數)可以作為另一個函數(稱為b
函數)的參數, b
函數最終可以傳回一個特定的值。
從原理上來說, b
函數在自己的函數體內呼叫了a
函數,所以需要把a
函數的名字當作實際參數傳遞給b
函數。如下:
//求最大值function getMax(a,b) { return a>b?a:b; } //求最小值function getMin(a,b) { return a<b?a:b; } //下面這個函數以函數為參數,最後傳回一個值function getM(func,num1,num2) { return func(num1,num2); } getM(getMax,1,2);//回傳2 getM(getMin,1,2);//回傳1
我們把a
函數的名字( getMax
或getMin
)傳給b
函數( getM()
),然後在b
函數內部呼叫傳入的a
函數,得到相關的結果。