JavaScript 函式寫法:具名、匿名、函式表達式與箭頭函式
在這篇文中 函式的構成與使用 已有簡單的說明函式的定義方式及使用方式。此篇便來詳細介紹函式的其他定義方式,也會把前篇的內容拿來比較一下。
函式宣告(Function Declaration)
具名函式(Named Function)
簡單的來說,具名函式 就是有名字的函式,透過名稱來呼叫這些函式。也就是透過呼叫的方式,可以讓我們重複的利用這些程式碼,讓程式碼更容易閱讀與維護。
function todo() {
// 執行事項
}
function calc() {
return 'something';
}小提醒
函式宣告會被 提升(Hoisting),也就是整個函式在程式執行前就已被建立,因此寫在後面也可以在前面呼叫:
// 15,可以正常執行
console.log(getSum(10, 5));
function getSum(x, y) {
return x + y;
}匿名函式(Anonymous Function)
匿名函式 是在函式定義時沒有指定名稱的函式,也就是說無法透過名稱來呼叫這些函式。匿名函式 通常只有當下被使用,不會出現被其他地方呼叫到的狀況,也較為簡潔。
document.querySelector('#Btn').addEventListener('click', function () {
// 執行事項
});注意
匿名函式沒有名稱可以指涉,所以 綁定事件 後就沒辦法用 removeEventListener() 解綁。需要解綁時請改用具名函式。
函式表達式(Function Expressions)
函式的宣告放在一般運算式的位置,這樣就可以建立一個函式了。
const funExpr = function () {
// 執行事項
};
const getNum = function () {
return 10;
};注意
函式表達式 不會被提升,必須先執行到那一行才能使用:
// 錯誤:Cannot access 'getSum' before initialization
console.log(getSum(10, 5));
const getSum = function (x, y) {
return x + y;
};箭頭函式(Arrow Function)
ES6 加入的語法,寫起來更短,也是現在最常見的寫法:
// 完整寫法
const getSum = (x, y) => {
return x + y;
};
// 只有一行 return 時,可省略大括號與 return
const getSum2 = (x, y) => x + y;
// 只有一個參數時,小括號也可以省略
const double = (x) => x * 2;注意
箭頭函式沒有自己的 this 與 arguments。在事件處理器中若要用 this 取得元素,就不能寫成箭頭函式,詳見 this 是什麼。
立即函式(IIFE)
定義完就馬上執行一次,用途是建立一個獨立的作用域,避免變數汙染全域:
(function () {
const secret = '只活在這個括號裡';
console.log(secret);
})();小提醒
有了 let、const 的區塊作用域與 ES 模組之後,立即函式的必要性已大幅降低,但在讀舊專案時還是很常遇到。
return 回傳
可以透過 return 這個指令將函式內的值回傳出去。且具有停止的功能,並將值回傳出去。
以下的兩種寫法不同,但達到的目的相同,也就打印出加總完畢後的結果。
寫法一:
function calc(x, y) {
console.log(x + y);
}
calc(10, 5);寫法二:
function getSum(x, y) {
return x + y;
}
console.log(getSum(10, 5));兩者的差別在於 值有沒有交出來:寫法一只能印出結果,寫法二拿到的值可以繼續運算、寫進畫面或傳給其他函式,彈性大得多。
小提醒
return 一執行,函式就結束了,後面的程式不會再跑。這個特性常被用來提早結束函式:
function showMsg(msg) {
if (!msg) return;
console.log(msg);
}各種寫法的比較
| 寫法 | 會被提升 | 有自己的 this | 常見用途 |
|---|---|---|---|
| 具名函式宣告 | 是 | 是 | 需要重複呼叫、需要解綁事件 |
| 匿名函式 | 否 | 是 | 當成參數直接傳入 |
| 函式表達式 | 否 | 是 | 把函式當值儲存 |
| 箭頭函式 | 否 | 否 | 回呼、簡短運算 |
| 立即函式 | 否 | 是 | 建立獨立作用域 |
常見問題
函式宣告與函式表達式有什麼差別?
函式宣告會被提升,寫在後面也能在前面呼叫;函式表達式是把函式指定給變數,必須先執行到那一行才能使用,否則會拋出錯誤。
箭頭函式與一般函式差在哪裡?
最關鍵的是箭頭函式沒有自己的 this 與 arguments,它沿用外層作用域的 this。此外它不能當建構函式使用,語法上也更精簡。
return 有什麼作用?
return 把值交回呼叫函式的地方,同時立即結束函式,後面的程式不再執行。沒有寫 return 的函式,回傳值是 undefined。
什麼是匿名函式,什麼時候會用到?
匿名函式是沒有名稱的函式,常被當成參數直接傳給其他函式,例如:事件監聽器 或 forEach() 的回呼。缺點是無法用名稱重複呼叫或解綁。
立即函式(IIFE)是做什麼的?
它在定義後立刻執行一次,用途是建立獨立的作用域,避免變數汙染全域。有了區塊作用域的 let 與 const 以及模組後,需求已大幅減少。