在學習 JavaScript 的過程中,「函式」是非常重要的基礎觀念。
你可以把函式想像成一組可以被重複使用的指令集合,例如計算平方、顯示訊息、處理資料等等。
學會正確地「定義」和「呼叫」函式,將讓你的程式更簡潔、更有彈性。
本篇文章將帶你認識最常見的函式寫法——函式宣告(Function Declaration),不僅語法簡單,還有一個非常實用的特性:可以先呼叫、後定義。讓我們一步步了解它的寫法、行為與優勢吧!
什麼是函式宣告?(Function Declaration)
在 JavaScript 中,「函式」就像是一個你可以重複使用的小工具,你可以把它想像成是一個包裝好的一組指令,只要叫用它,它就會幫你完成一件事。函式可以讓程式碼更乾淨、更有邏輯、更容易維護。
函式宣告是什麼?
所謂的函式宣告(Function Declaration),是 JavaScript 中最標準、最傳統的建立函式的方式。
這種方式使用 function 這個關鍵字來開頭,後面接上函式名稱、參數和大括號 {} 包住的程式碼內容。
語法結構:
function 函式名稱(參數1, 參數2, ...) {
// 在這裡寫下這個函式要做的事情
return 回傳的結果;
}function:固定關鍵字,用來宣告一個函式。函式名稱:你自訂的名字,用來呼叫這個函式(就像你幫它取了一個綽號)。(參數):函式可以接收「外部傳入的資料」作為輸入,這些資料稱為參數。{}:包住函式的主體,也就是這個函式實際會執行的程式內容。return:用來回傳函式的執行結果,讓你在其他地方可以取得這個結果。
實際範例說明:
function square(x) {
return x * x;
}在這個例子中,我們做了幾件事情:
- 使用
function開始宣告函式。 - 命名為
square(代表平方的意思)。 - 在括號中定義了一個參數
x,代表使用者呼叫這個函式時要傳進來的一個數字。 - 函式內部的
return x * x;代表將這個數字乘以它自己,然後回傳結果。
🧠 思考:這個函式做了什麼?
- 如果你執行
square(4),程式會把4傳給參數x。 - 函式執行後會回傳
4 * 4,也就是16。 - 所以這行
square(4)會得到結果16,你可以用來顯示、儲存或做進一步運算。
💡 延伸說明:函式的意義
想像一下,如果你需要多次對不同的數字做平方運算,那你會怎麼寫呢?
console.log(3 * 3);
console.log(7 * 7);
console.log(10 * 10);這樣寫會重複很多類似的程式碼,閱讀和維護都很麻煩。如果你有一個 square 函式,就可以變成這樣:
console.log(square(3));
console.log(square(7));
console.log(square(10));這不但讓程式更有結構、容易理解,還能減少出錯機會。
小結
函式宣告是建立函式的一種方式,具有以下特點:
| 特點 | 說明 |
|---|---|
| ✅ 結構清晰 | 使用 function 關鍵字開頭,標明這是一個函式 |
| ✅ 可讀性佳 | 函式有自己的名字,方便識別和呼叫 |
| ✅ 可重複使用 | 一次定義,無限次使用,只要傳入不同的參數 |
| ✅ 可回傳結果 | 用 return 把計算結果帶出來,給其他地方使用 |
函式宣告的特性:可以「先呼叫、後定義」
當你剛開始學寫程式的時候,腦中可能會自然有個直覺:
「我必須先告訴電腦這個函式是什麼,它要做什麼事情,接著才可以使用它。」
「因為如果電腦還不知道這個函式長什麼樣、會做什麼,它當然沒辦法幫我執行。」
這個想法就像是寫一份說明書給機器人:
👤「這台機器人現在還不會做餅乾,所以我要先教它做餅乾(定義函式),再叫它開始做(呼叫函式)。如果我一開始就叫它做餅乾,它會傻住,因為它根本不知道該怎麼做!」
因此,許多初學者會理所當然地認為,程式碼的順序應該是:
- 先寫好函式的定義(說明函式怎麼運作)
- 再呼叫這個函式去做事(讓它執行)
對比寫法:
// 初學者預期的順序
function greet() {
return "Hello!";
}
console.log(greet()); // OK這樣的順序很自然,因為我們是先告訴電腦「greet 是什麼」,再使用它。
但驚訝的是…
在 JavaScript 中,如果你這樣寫:
console.log(greet()); // 這行先出現!
function greet() {
return "Hello!";
}程式一樣能正常運作!這對初學者來說會是一個衝擊 ——「咦?函式不是應該要先寫嗎?怎麼可以先用?」
所以我們才會說,剛學程式時會以為一定要先定義函式再呼叫,但其實 JavaScript 的函式宣告寫法會自動被「提前處理」,讓你就算把呼叫寫在前面也沒關係。
這就是下一節要介紹的「Hoisting(提升)」所帶來的魔法。
為什麼可以先呼叫後定義?——來自 Hoisting(提升)機制
這個看似魔法般的行為,其實是 JavaScript 語言的一個設計特性:Hoisting(提升)。
Hoisting 是什麼?JavaScript 中看不見的「預先搬運工」
在 JavaScript 中,當你執行一段程式碼時,並不是從上到下立刻照順序一行一行跑。
事實上,在真正執行之前,JavaScript 會先進行一個稱為「Hoisting(提升)」的預處理動作。
🏗️ 換句話說:
當程式剛開始執行時,JavaScript 解譯器會先幫你掃描整段程式碼,並且將某些東西「偷偷搬到最上面」的意思 —— 就像在開場前,舞台工人早就把燈光、道具安排好,只等你演出。
這些被提前處理的東西,包含:
JavaScript 執行流程:用比喻說給你聽
想像你寫的程式是一份「考卷」,而 JavaScript 是一位很聰明的老師。
在正式改卷之前,這位老師會先快速掃過一遍你的答案卡:
「喔~你有定義
function greet(),我記下來了,等會兒可以直接用喔!」
所以即使你把 function greet() 寫在最下面,JavaScript 也會在正式執行第一行程式碼前,就已經「提前知道」這個函式的存在,能夠正常執行:
// 雖然還沒寫 greet 的內容,但 JavaScript 已經知道有 greet 函式了
console.log(greet()); // 👉 可以正常執行!
function greet() {
return "Hello!";
}這正是 Hoisting(提升)帶來的好處:讓你的函式可以更自由地安排位置,讓程式碼結構更靈活。
不過,這種便利性只存在於「函式宣告」這一種寫法中。
JavaScript 還有另一種常見的函式寫法,叫做「函式表達式(Function Expression)」,它的行為可就不一樣了——
函式宣告 vs 函式表達式(Function Expression)
你可能聽過另一種建立函式的方式叫「函式表達式」,像這樣:
const square = function(x) {
return x * x;
};這種方式看起來和函式宣告差不多,實際上卻不會被提升。
這也就表示,你不能在函式被定義之前就呼叫它,否則會發生錯誤。
舉反例:函式表達式不會被提升!
對比一下這段使用「函式表達式」的寫法,就會出錯:
console.log(greet()); // ❌ TypeError: greet is not a function
const greet = function() {
return "Hello!";
};這裡程式會出錯,原因如下:
const greet = ...是一個變數賦值的行為,不是函式宣告。- JavaScript 不會把整個「賦值動作」提前,所以在執行
console.log(greet())時,greet的值還是undefined。 - 也就是說,變數本身是存在的(因此不會是 ReferenceError),但它的值還沒準備好,所以會出現 TypeError。
差別在哪?
| 類型 | 會被提升? | 可以先呼叫? | 範例寫法 |
|---|---|---|---|
| 函式宣告 | ✅ 會 | ✅ 可以 | function greet() {} |
| 函式表達式 | ❌ 不會 | ❌ 不行 | const greet = function() {} |
總結:初學者為什麼要學會函式宣告?
| 優點 | 說明 |
|---|---|
| ✅ 語法簡潔 | 使用 function 關鍵字開頭,結構清楚易懂 |
| ✅ 可以先呼叫 | 程式碼邏輯更靈活,不受順序限制 |
| ✅ 可讀性高 | 清楚表達這是一個具名函式,方便日後維護 |
| ✅ 適合教學與範例 | 教學資源與開發文件多以函式宣告為主,學起來更有一致性 |
對初學者而言,了解函式宣告不只是學會一種寫法,而是開始理解程式語言背後的執行順序、作用域與邏輯安排。
這些觀念將會是你進階學習 JavaScript 的基礎,未來當你學習事件處理、非同步程式或模組架構時,這些知識都會派上用場。
現在就動手寫幾個函式試試看吧,從計算機功能、問候語、轉換數值等簡單功能開始練習,你會發現程式其實沒有想像中困難!