函式是一段有組織、可重複使用的程式碼區塊,用來執行某個動作。 在 JavaScript 中,定義函式的方式有好幾種。 這裡我們會介紹_函式宣告_和_函式運算式_。 其他做法,像是箭頭函式,會在其他概念中介紹。
在 JavaScript 中,定義函式的標準做法是_函式宣告_,也稱為_函式定義_或_函式敘述_。
它由 function 關鍵字、函式名稱,以及一串以逗號分隔、包在括號中的參數組成。
接著是包在大括號裡的函式主體(定義函式做什麼的敘述集合)。
function someName(param1, param2, param3) {
// ...
}
在 JavaScript 中,只要寫出函式名稱,後面接著一對包含引數的括號,就能呼叫函式。
someName(arg1, arg2, arg3);
在 JavaScript 中,光是寫出函式名稱並不會呼叫函式。
function sayHello() {
console.log('Hello, World!');
}
sayHello;
// => [Function: sayHello]
// The text representations varies between environments.
sayHello();
// => 'Hello, World!'
在函式主體中使用參數時,要留意可能對傳入函式的原始值造成副作用。 在 JavaScript 中,引數是原始值參照的複本。 實際上代表什麼意思,取決於引數的資料型態。
原始資料型態的值是_不可變的_。 所有「修改」一律會建立一個新的原始值。 因此,函式主體中對引數做的任何事,都不會影響到原始值。
const num = 0;
function increase(number) {
number = number + 1;
}
increase(num);
num;
// => 0
像是_物件_、陣列、_函式_這類的值就不一樣。 由於複製的是參照,重新賦值並不會影響原始值。 不過,因為你處理的是淺拷貝,在函式主體中修改引數,也會一併改變傳入的原始值。
const nums = [0, 1, 2, 3, 4];
function pushFive(arr) {
arr.push(5);
}
pushFive(nums);
nums;
// => [0, 1, 2, 3, 4, 5]
在 JavaScript 中,函式宣告裡定義的所有參數預設都是選用的。
如果呼叫函式時提供的引數比參數少,缺少的引數在函式主體裡會是 undefined,請參閱 Null 與 Undefined。
在許多情況下,如果沒有傳入值,或傳入的是 undefined,用_預設_值初始化參數會更合理。
做法是直接在函式定義中指定預設參數。
function someName(param1 = defaultValue1, param2 = defaultValue2) {
// ...
}
呼叫函式時傳入的引數可以比函式定義中的參數還多。 所有引數,包括多出來的那些,都能在 arguments「陣列」 裡找到。
也可以定義接受任意數量引數的函式(可變參數函式),詳情請參閱其餘與展開運算子中的其餘參數。
return 敘述return 敘述會結束函式的執行,並指定一個回傳給函式呼叫者的值。一個函式可以有多個 return 敘述。
function checkNumber(num) {
if (num === 0) {
return 'You passed 0, please provide another number.';
}
return 'Thanks for passing such a nice number.';
}
一個沒有回傳值、或沒有 return 敘述的函式,其結果是 undefined。
JavaScript 中沒有隱含的 return。
function nakedReturn(a) {
a * 2;
return;
}
nakedReturn(1);
// => undefined
function noReturn(a) {
a * 2;
}
noReturn(1);
// => undefined
在 JavaScript 中,函式只能回傳恰好一個值。 如果想傳遞更多資訊,必須先把它們合併成單一實體,通常是合併成物件或陣列。
function divide(a, b) {
return {
quotient: Math.floor(a / b),
remainder: a % b,
};
}
函式宣告是一個獨立的敘述。 但有時候,把函式定義成另一個運算式的一部分會更方便,例如用在賦值中、當成函式參數(回呼),或當成物件裡的值。 這可以用函式運算式做到。 它的語法和函式宣告相同,差別在於可以省略函式名稱,建立一個_匿名函式_。
const someFunction = function (param) {
// ...
};
someOtherFunction(function (param) {
// ...
});
const obj = {
someFunction: function (param) {
// ...
},
};
在 JavaScript 中,函式會引入一個新的執行環境。 在函式內定義的變數,在該函式之外無法存取。 但在父作用域(定義函式本身所在的作用域)中定義的變數,在函式內可以存取。 MDN 關於作用域的文件展示了這種行為的範例。
想進一步了解 JavaScript 中的變數作用域,請看看閉包。