和其他語言中一樣,函數,是被設計爲執行特定任務的代碼塊。定義函數的意義就在於封裝重複使用的代碼。一起看看吧。
1. 定義JavaScript函數
在JS中,創建自定義函數的語法如下:
- JavaScript 函數通過 function 關鍵詞進行定義。
- 關鍵詞後是函數名,可以使用字符、數字和下劃線,但是名稱不能以數字開頭,也不能與JS保留字衝突,函數名是大小寫敏感的。一般來說,函數名應該具有描述性,常常使用動詞表示,比如addTask()、calculate()、init()等。
- 函數名後是圓括號(),其中包含指定函數的參數,多個參數間由逗號分隔。函數參數(Parameters)是在函數定義中所列的名稱,當調用函數時由函數接收的真實的參數值(Arguments)。在函數中,參數是局部變量。
- 函數執行的代碼被放置在花括號 { } 中。
- 可以從函數返回值,在任何情況下,函數都通過return語句返回值。函數返回值可以是任意類型的文本值或者變量。函數中的return語句只能被執行一次,但是函數中定義的return語句數量沒有限制。當遇到一個return語句,函數的執行就會終止。如果函數沒有return語句,則會自動返回underfined值。
定義函數後,可以使用如下形式調用:
functionName(Arguments);
注意:() 運算符調用函數,不使用 () 訪問函數將返回函數聲明而不是函數結果。
2. 關於函數參數
關於JS函數的參數,有幾點需要強調:
(1)JS 函數不檢查參數的類型
JS是弱類型的語言,對於任何變量都沒有聲明類型,所以函數參數似乎沒有任何類型檢查的。因此,爲了函數功能的準確,在必要的時候需要在函數體內添加自己的檢查類型。
(2)JS 函數不檢查參數的數量
JS中對於參數數量不正確的情況也是不會報錯的,但是結果可能是函數無法正常工作。
arguments.length 屬性返回函數接收的參數數量:
function myFunction(a, b) {
return arguments.length;
}
myFunction() //0
myFunction(4,3) //2
myFunction(4, 3, 5) //3
(3)JS 參數沒有默認值
JS中的參數無法設置默認值,如果函數調用時沒有傳遞某個參數值,這個參數的值就是undefined,這也是造成函數無法正常工作的原因,們可以通過確認參數變量不是undefined來測試函數參數是否收到值。要創建類似默認值的功能,可以在函數體中進行賦值擦操作。同時,因爲調用函數時無法跳過參數,所以在合適的情況下可以將undefined作爲參數值傳入。
參數值的傳遞方式有兩種:按值傳遞或按引用傳遞。
在JS中,簡單值(數字、字符串和布爾值)是按值傳遞的。也就是在函數調用中,實際的變量並沒有傳遞給函數,傳遞的只是變量的值,因此在函數中對簡單值的改變對函數外的變量沒有影響。
而數組和對象這些複雜類型的值是按照引用傳遞的。如果在函數中改變了這些變量,函數外的變量也將改變。
3. 作爲對象的函數
JavaScript 中的 typeof 運算符會爲函數返回 "function",但是JS中的函數具有獨特的性質:函數本身也是對象。也就是說,可以將函數作爲變量使用:
function myFunction(a, b) {
return a * b;
}
var x = myFunction(4, 3) * 2; //函數可以在表達式中使用
toString() 方法以字符串返回函數:
function myFunction(a, b) {
a += 1
return a * b;
}
myFunction.toString(); //function myFunction(a, b) { a += 1 return a * b; }
3. 匿名函數
匿名函數,顧名思義就是沒有名稱的函數。把一個普通函數變成匿名函數,總共分三步:
(1)去掉函數名
(2)用圓括號括起來
(3)後面加上括號直接執行或將需要傳遞的參數寫在括號裏。
function myFunction(a, b) {
return a * b;
}
myFunction(2,4); //8
//將上述函數改寫成匿名函數
(function (a, b){
return a * b;
})(2,4); //8
匿名函數主要的使用場景由:賦值給變量、賦值給對象屬性、用作函數調用中傳遞的參數值。
注意:使用匿名函數表達式時,函數的調用語句,必須放在函數聲明語句之後!!!
4. 嵌套函數
在JS中,函數可以嵌套,也就是說,可以在函數體中定義新的函數。舉個栗子:
function compare(arrA, arrB){
function sum(arr){
var s=0;
for(var i=0; i<arr.length; i++)
s += arr[i]
return s
}
return sum(arrA) < sum(arrB)
}
嵌套函數有一些有意思的特性:
- 嵌套函數(內部函數)有自己的作用域,嵌套函數的作用域只在函數體內,而且內部函數自動具備對父函數中的局部變量的訪問權。
- 內部函數從全局作用域來看是“隱藏的",也就是無法從外部函數之外調用內部函數。