JavaScript基礎介紹:函式與箭頭函式
什麼是函式?
函式(Function)是一種包裝程式的方式,可以重複使用。它會基於輸入的值執行某些處理程序後,再將結果回傳的機制。也就是說,函式可以接收一個(或數個)值,並把這個值轉換為另外一個結果後回傳。
每個程式語言都有其預定提供的函式,除了預定的函式之外,開發人員可以自行定義函式,這種函式被稱為自定義函式。JavaScript也不例外,除了提供內建函式外,也可以讓開發人員自己定義函式。
函式優點
由於函式具有下面幾項優點,常被廣泛的使用在程式中:
- 可以重複被呼叫使用,簡化程式的流程
- 容易對程式進行除錯
- 寫程式時便於分工合作
定義函式
依照MDN上面的說明:
可以知道自行定義函式有下面幾個方式:
- 利用function定義
- 利用Function建構子定義
- 利用函式常值定義
- 利用箭頭函式定義
function指令定義
一般來說,最間單最基礎的方式是利用fuction來定義函式,透過這個關鍵字告訴JavaScript接下來要宣告一個函式了。這種方式被稱為function declaration,其語法如下:
function 函式名稱(參數,...) {
...處理程序...
return 傳回值
}
例如下面是一個計算矩形的函式,只要輸入寬度與高度,就可以得到矩形的大小:
function rectArea(width, height) {
return width * height;
}
原則上來說,函式需要一個名稱才可以讓JavaScript來呼叫。然而,在某些情況下可以不需要名稱就可以被執行,這種函式被稱為「匿名函式」。我們留待後面說明。
緊接在函式名稱後面的括號,裡面放的值為參數(parameter)。參數用來表明該函式將要接收的值,就是該函數執行時所需的資料。
傳回值則是函式處理後產生的結果,一般會透過return來決定要回傳的內容是什麼。return指令一般會寫在函式的末端。但是也不是每個函式都需要有傳回值,如果沒有傳回值可以省略return指令不寫,JavaScript會自動幫我們回傳undefine。所以,我們可以把undefine當作函式回傳的預設值。
此外,有些函式僅當作執行某段邏輯為目的而存在,並不需要我們輸入任何的參數值。然而要特別注意的是,即使如此,函式後面的括號仍然不可以省略。
Function建構子(constructor)定義
Function物件為JavaScript的內建物件。基本上來說,每個JavaScript函式都是Function物件。因此,我們也可以透過這個物件來定義函式。
var 變數 = new Function(參數,...,函式處理程序)
可以省略new:
var 變數 = Function(參數,...,函式處理程序)
相對於function指令的定義方式,Function建構子可以使用字串定義參數與函式本體。除此之外,其實未必需要使用這種Function建構子的定義方式。
函式常值定義
除了前面兩種方式外,還可以使用常值定義函式,又稱為function expression(函式表達式)。可以帶入變數或當成參數傳入另一個函式,甚至可作為傳回值回傳。
var 變數 = function(參數,...) {
...處理程序...
return 傳回值
}
例如:
var rectArea = function (width, height) {
return width * height;
}
與function指令定義方式的差異
乍看之下,這個定義方式雖與前面的function指令定義法很像,但還是有下面幾個差異:
# 是否可以在函式前面呼叫函式?
透過function指令定義的函式可以在定義的位置前面呼叫該函式;而使用函式常值定義的函式,則不可以在該定義的位置前面呼叫之,會出現undefine的結果。舉例來說:
//function指令定義的函式rectArea(2,5)function rectArea(width, height) {
return width * height;
}
可以被執行:
但是,下面的程式碼就會出錯。
//function指令定義的函式console.log(rectArea(5, 5));
var rectArea = function (width, height) {
return width * height;
}
#函式定義後記憶體是否回收?
透過function指令定義的函式,只要被定義過後就無法從記憶體中刪除並回收。而使用函式常值定義的函式,則是正常的跟著變數的生命週期運作。可能在定義完畢後直接被回收或是跟著變數的參考被移除時被回收。
函式的執行
寫在函式裡面的程式內容在JavaScript程式剛啟動時並不會被執行。必須經過「呼叫」(invoke)的程序。呼叫函式的方式很簡單,只要在函式名稱後面加上一個小括號就可以了。例如:
函式名稱()
// 或是
函式名稱(參數)
一但函式被呼叫後,就會開始執行函式中的程式區塊,當區塊中的最後一行被執行完畢,該函式就結束工作。如果在執行的過程中,發現了return 的關鍵字,函式就會返回return 的數值。
函式特性
函式有下面幾項特性:
可重複呼叫
函式可以被重複呼叫。例如下面的程式碼,我們就重複呼叫了4次Hello函式。
function Hello(){
alert("Hello World");
}Hello();
Hello();
Hello();
Hello();
具區域概念
函式除了可以被重複呼叫外,並且具有區域的概念。在 ES6 尚未出現之前,JavaScript 的變數,其最小的有效範圍是以 function
做界線的區隔。函式在尚未被呼叫之前是不會發生作用的。
如下面函式,即使已經將函式放入頁面的<script>中,只要該函式尚未被呼叫,就不會發生任何作用。
function Hello(){
alert("Hello World");
}
我們可以透過Hello(),可以呼叫函式:
function Hello(){
alert("Hello World");
}Hello()
箭頭函式(Arrow Function)
箭頭函式是ES6新增的一種創造函式的方式。利用這種方式可以簡化函式常值的定義方式。在箭頭函式中不會用到 function 關鍵字。取而代之的是以箭頭( =>
)連接參數與函式本體。語法如下:
(參數,...)=> { ...函式本體... }
上面的語法雖然已經看起來很簡單了,但依據不同的狀況還可以更加簡化。
假設我們有一個一般的函式:
function (x){
return x * 10;
}
使用箭頭函式來表示的時候可以改成:
(x) => {
return x * 10;
}
在上面的程式裡,我們省略了function關鍵字。
# 函式本體只有單行敘述,可以省略表示區塊的大括號。
(參數,...)=> ...函式本體...
# 函式本體處理後的值即為回傳值,可以省略return指令。例如:
let sum = (x,y)=> x + y
因此,上面的程式碼可以省略為:
(x) => x * 10;
# 函式只有一個參數時,可以省略中括號
上面的程式碼可以再近一步省略為:
x => x * 10;
如果有兩個以上的參數,就不可以省略,例如下面的程式碼:
// 傳統函式
function (x, y){
return x + y + 20;
}// 箭頭函式
(x, y) => x + y + 20;
箭頭函式的中括號即不可以省略。
# 若函式沒有任何參數時,不可以省略中括號
例如下面的程式碼:在傳統的函式下,已經沒有任何參數時,在簡化為箭頭函式的時候,就不可以省略中括號。
結語
以上簡單的說明函式的定義、宣告以及呼叫函式的方式。當程式越來越複雜時,程式的維護與除錯的難度就會跟著上升,函式是一個常常被軟體工程師用來簡化程式的一個方式,將程式重複的部分寫成函式,不僅簡化了程式碼,在維護與除錯上也會變得較為清晰方便。因此,學習掌握函式的各項性質與用法,在程式撰寫上便得以更加得心應手。