Skip to content

JavaScript 函式寫法:具名、匿名、函式表達式與箭頭函式

函式的定義方式:具名、匿名與箭頭函式

在這篇文中 函式的構成與使用 已有簡單的說明函式的定義方式及使用方式。此篇便來詳細介紹函式的其他定義方式,也會把前篇的內容拿來比較一下。

函式宣告(Function Declaration)

具名函式(Named Function)

簡單的來說,具名函式 就是有名字的函式,透過名稱來呼叫這些函式。也就是透過呼叫的方式,可以讓我們重複的利用這些程式碼,讓程式碼更容易閱讀與維護。

js
function todo() {
  // 執行事項
}

function calc() {
  return 'something';
}

小提醒

函式宣告會被 提升(Hoisting),也就是整個函式在程式執行前就已被建立,因此寫在後面也可以在前面呼叫:

js
// 15,可以正常執行
console.log(getSum(10, 5));

function getSum(x, y) {
  return x + y;
}

匿名函式(Anonymous Function)

匿名函式 是在函式定義時沒有指定名稱的函式,也就是說無法透過名稱來呼叫這些函式。匿名函式 通常只有當下被使用,不會出現被其他地方呼叫到的狀況,也較為簡潔。

js
document.querySelector('#Btn').addEventListener('click', function () {
  // 執行事項
});

注意

匿名函式沒有名稱可以指涉,所以 綁定事件 後就沒辦法用 removeEventListener() 解綁。需要解綁時請改用具名函式。

函式表達式(Function Expressions)

函式的宣告放在一般運算式的位置,這樣就可以建立一個函式了。

js
const funExpr = function () {
  // 執行事項
};

const getNum = function () {
  return 10;
};

注意

函式表達式 不會被提升,必須先執行到那一行才能使用:

js
// 錯誤:Cannot access 'getSum' before initialization
console.log(getSum(10, 5));

const getSum = function (x, y) {
  return x + y;
};

箭頭函式(Arrow Function)

ES6 加入的語法,寫起來更短,也是現在最常見的寫法:

js
// 完整寫法
const getSum = (x, y) => {
  return x + y;
};

// 只有一行 return 時,可省略大括號與 return
const getSum2 = (x, y) => x + y;

// 只有一個參數時,小括號也可以省略
const double = (x) => x * 2;

注意

箭頭函式沒有自己的 thisarguments。在事件處理器中若要用 this 取得元素,就不能寫成箭頭函式,詳見 this 是什麼

立即函式(IIFE)

定義完就馬上執行一次,用途是建立一個獨立的作用域,避免變數汙染全域:

js
(function () {
  const secret = '只活在這個括號裡';
  console.log(secret);
})();

小提醒

有了 letconst 的區塊作用域與 ES 模組之後,立即函式的必要性已大幅降低,但在讀舊專案時還是很常遇到。

return 回傳

可以透過 return 這個指令將函式內的值回傳出去。且具有停止的功能,並將值回傳出去。

以下的兩種寫法不同,但達到的目的相同,也就打印出加總完畢後的結果。

寫法一:

js
function calc(x, y) {
  console.log(x + y);
}

calc(10, 5);

寫法二:

js
function getSum(x, y) {
  return x + y;
}

console.log(getSum(10, 5));

兩者的差別在於 值有沒有交出來:寫法一只能印出結果,寫法二拿到的值可以繼續運算、寫進畫面或傳給其他函式,彈性大得多。

小提醒

return 一執行,函式就結束了,後面的程式不會再跑。這個特性常被用來提早結束函式:

js
function showMsg(msg) {
  if (!msg) return;

  console.log(msg);
}

各種寫法的比較

寫法會被提升有自己的 this常見用途
具名函式宣告需要重複呼叫、需要解綁事件
匿名函式當成參數直接傳入
函式表達式把函式當值儲存
箭頭函式回呼、簡短運算
立即函式建立獨立作用域

常見問題

函式宣告與函式表達式有什麼差別?

函式宣告會被提升,寫在後面也能在前面呼叫;函式表達式是把函式指定給變數,必須先執行到那一行才能使用,否則會拋出錯誤。

箭頭函式與一般函式差在哪裡?

最關鍵的是箭頭函式沒有自己的 thisarguments,它沿用外層作用域的 this。此外它不能當建構函式使用,語法上也更精簡。

return 有什麼作用?

return 把值交回呼叫函式的地方,同時立即結束函式,後面的程式不再執行。沒有寫 return 的函式,回傳值是 undefined

什麼是匿名函式,什麼時候會用到?

匿名函式是沒有名稱的函式,常被當成參數直接傳給其他函式,例如:事件監聽器forEach() 的回呼。缺點是無法用名稱重複呼叫或解綁。

立即函式(IIFE)是做什麼的?

它在定義後立刻執行一次,用途是建立獨立的作用域,避免變數汙染全域。有了區塊作用域的 letconst 以及模組後,需求已大幅減少。

延伸閱讀