第 361 篇 · 第 14 卷 前端,沒有極限 2026 年 6 月 9 日 · 台北
ls -lt ./posts --since=2013 REC · node 361 · uplink

javascript

鐵人賽:JavaScript 函式與參數

2017 年 12 月 14 日 · 4 分鐘閱讀 · By Wang Casper

函式可以將參數傳入,使得函式的可用性提高許多,不過其中也有許多小技巧及方法可以運用,以下我們用 悠遊卡的概念 來說明此段。

小明的悠遊卡裡面有 1000 元,他要儲值一些零用錢進悠遊卡內 (真是優秀青年,這麼多錢還繼續儲),好讓他可以繼續搭乘捷運。

傳入變數

以下是一個簡單的函式,用來更新悠遊卡的金額。小明將錢 cash 投入機器內後,按下執行按鈕 updateEasyCard() 就會回傳更新後的悠遊卡金額。

var originCash = 1000; // 悠遊卡內原有的現金
function updateEasyCard (cash) { // 傳入儲值金進入悠遊卡
  var newCash = cash + originCash;
  console.log('我有 ' + newCash + ' 元');
}
updateEasyCard(1000); // 我有 2000 元
updateEasyCard(2000); // 我有 3000 元

但如果機器沒有設定好,小明還沒有投入任何金額就按下 updateEasyCard() 就會跳出 NaN (Not a Number) 的錯誤 。

updateEasyCard(); // 我有 NaN 元

所以有些函式會透過 || 來加入預設值,在沒有輸入任何值的情況下會使用預設值代替,這邊就先將預設值設為 100 (佛心機器,沒投錢也會給 100)。

var originCash = 1000;
function updateEasyCard(cash) {
  var money = (cash || 100) + originCash;
  console.log('我有 ' + money + ' 元');
}

updateEasyCard(); // 我有 1100 元

這樣,至少不會出現錯誤了,但會出現另一個問題,假設函式中真的需要使用 0false 這種值傳入時,他一樣會使用前者所套用的值。

updateEasyCard(0); // 我有 1100 元

0 會被強制轉型成 false,所以兩者都會被替代。

複雜的判斷式

|| 本身就是一個判斷式,如果簡單的判斷式沒辦法滿足需求,那麼就使用更複雜的判斷式來寫,以下範例:如果 cash 是 false,且 cash 不等於 0 的情況, cash = 100。

var originCash = 1000;
function updateEasyCard(cash) {
	if (!cash && cash !== 0) {
	  cash = 100;
	}
  var money = cash + originCash;
  console.log('我有 ' + money + ' 元');
}

updateEasyCard(); // 我有 1100 元
updateEasyCard(0); // 我有 1000 元

當然,還有一種情況就是傳入的並非數值而是字串,這樣則會造成金額也自動轉換成字串。

updateEasyCard('1000'); // 我有 10001000 元

那麼就需要先將文字轉成數值,避免原始的數值被轉換為字串。

var originCash = 1000;
function updateEasyCard(cash) {
  cash = Number.parseInt(cash);
	if (!cash && cash !== 0) {
	  cash = 100;
	}
  var money = cash + originCash;
  console.log('我有 ' + money + ' 元');
}

updateEasyCard('100'); // 我有 1100 元
updateEasyCard('這不是錢'); // 我有 1000 元 (無法被轉換)

ES6 預設函式變數

在 ES6 中提供更簡潔的方式來解決此問題,可以直接在傳入的參數賦予預設值,此預設值也不需要額外的帶入判斷式就能達到以上效果(但文字問題依然要自己修正喔)。

var originCash = 1000;
function updateEasyCard(cash = 100) {
  var money = cash + originCash;
  console.log('我有 ' + money + ' 元');
}

updateEasyCard(); // 我有 1100 元
updateEasyCard(0); // 我有 1000 元

arguments

假設小明零錢很多,他要一個一個投進去機器內儲值,這樣參數該如何設計?

除此之外,JavaScript 有預設的參數 arguments 可直接帶入,這種參數不須預先設定,所有函式都內建此參數,他會將呼叫函式所帶入的參數一並透過陣列的方式傳入。

var originCash = 1000;
function updateEasyCard() {
  var cash = 0;
  console.log(arguments); // 這裡可以看到 arguments 的結構
  for (var i = 0; i < arguments.length; i++) {
    cash += arguments[i];
  }
  var money = cash + originCash;
  console.log('我有 ' + money + ' 元');
}

updateEasyCard(0); // 我有 1000 元
// arguments = [];

updateEasyCard(10, 50, 100, 50, 5, 1, 1, 1, 500); // 我有 1718 元
// arguments = [10, 50, 100, 50, 5, 1, 1, 1, 500];

不過 arguments 實際在使用時會有一些小問題,像是範例中為何是使用 for 迴圈,而不是使用 forEach (forEach 可以使用在陣列上),主要原因是 arguments 並非真正的 陣列,它是 類陣列(Array-like) 的物件,因此無法使用許多陣列相關的方法。

相關文件可查閱:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments