iT邦幫忙

2021 iThome 鐵人賽

DAY 10
1
Modern Web

JavaScript 魔法入門 - 從入門到中階觀念系列 第 10

入門魔法 - function 函式

前情提要

艾草:「你可以幫我算一下 100 + 100 是多少嗎?」

「200 啊...」

艾草:「那在加 6 次 100 呢?」

「...? 妳在幹嘛呀,啊是不會自己算喔。」

艾草:「啊我就數學爛啊!我在算你的魔力總量多少了啦。」

「沒有什麼方便計算的魔法嗎?」

艾草:「啊,我想到了啦,那今天來教你函式好了,函式可以包裝計算功能用喔。很方便的唷~~
(≖‿ゝ≖)✧ 」
https://ithelp.ithome.com.tw/upload/images/20210924/20139066eB0IvBD43M.png

(唉... 數學不會背叛你... 因為不會就是不會,嗚嗚嗚嗚嗚)


函式

函式可以拿來包裝各個你想執行的任務,並透過呼叫函式,來多次執行這個任務。

例如可以透過函式來做加法計算功能,而當你需要丟數字進去運算時,就可以不斷地去呼叫該函式,並得到相加的數字。

讓我們先來了解應該如何定義函式吧?

函式的組成

  1. 函式的名稱(可自定義)
  2. 小括號 () 用來放置參數,可用,逗號分隔每個參數
  3. 大括號 {} 內部可以放想執行的 JavaScript 程式碼

當我們透過以上三個步驟組合函式後,函式會長成什麼樣子呢?

函式陳述式

function test(){
	console.log("Hello World!")
}

沒錯,這個樣子就完成了,但你會發現你想印出來的 "Hello World!" 根本沒印出來!等等先不要懷疑自己寫錯了,其實是因為你沒有呼叫函式啦!

該如何呼叫呢?其實就是透過我們自定義的名稱,含後面的()小括號,就可以呼叫成功囉!

function test(){
	console.log("Hello World!")//Hello World!
}
test()

真是太好了,可喜可賀。

但也不是每個函式都需要有名稱的,有些函式也可以是匿名的,例如用函式表達式來定義的函式。

函式表達式

函式表達式該如何撰寫呢?
首先,先宣告一個變數後,在將一個函式賦予給該變數。

let test = function(){
	console.log("Hello World!")//Hello World!
}
test()

而函式表達式的呼叫方式是變數名稱加上()小括號。

至於什麼是陳述式、表達式,未來學習中階魔法時會介紹到唷!

知識點:函式

  • 函式的定義方式有函式陳述式、函式表達式
  • 函式的組成包含:名稱、參數、想執行的程式碼
  • 記得要呼叫函式,函式才會執行

參數

還記得函式的組成第二點有提到參數嗎?那參數又是什麼呢?

讓我們用一開始說到的加法計算功能來了解參數吧!

讓我們來設定兩個參數,分別為 num1 、num2:

function add (num1,num2){
	console.log(`${num1 + num2}`)//num1 、 num2 參數會被帶入執行,印出 3
}
add (1,2)

參數是可以自定義的,可以依據情境定義參數後,在呼叫函式時,傳參數進去。

那如果今天我定義了兩個參數卻只傳一個參數進去會報錯嗎?

function add (num1,num2){
	console.log(num2)//undefined
	console.log(`${num1 + num2}`)//NaN
}
add (1)

可以看到參數二的地方因為未給值,會被賦予 undefined

如果要解決這個問題可以透過預設帶入參數的方式,可以透過 = 號提前賦予參數預設值,這樣參數在呼叫時未給予值,也可以帶入預設值,範例如下:

function add (num1,num2 = 0){
	console.log(num2)//0
	console.log(`${num1 + num2}`)//1
}
add (1)

呼叫時未給予參數 num2 值時,因為該參數已經有預設值了,會帶入 0 。

知識點:參數

  • 參數可藉由 , 逗號的方式分隔
  • 參數只存活在大括號內
  • 定義的參數少於傳進去的參數時,會自動將未被定義的參數賦予 undefined
  • 可以預設帶入參數的值,如果呼叫時未給予該參數值時會賦予預設值

而參數只能存活在函式的 {} 大括號內,那當我們希望拿到函式回傳的值要怎麼辦呢?

可以使用 return 的方式,接下來讓我們了解 return 吧!


return

讓我們來學學 return 是怎麼運作的吧!

在函式內可以透過 return 回傳值,並將該值賦予到呼叫它的變數上,如下:

function calcBmi(heightNum, weightNum) {
  let bmi = (weightNum / (((heightNum / 100) * heightNum) / 100)).toFixed(2);
  return bmi; //回傳 bmi 到呼叫它的地方
}
let shannonBmi = calcBmi(168, 55); //賦予函式回傳的值到變數上
console.log(shannonBmi); //19.49

當初學 return 的時候卡關了一小陣子,一直想不通怎麼一直丟來丟去的,後來就一直會提醒自己 return 就是會回傳值到呼叫它的地方,當執行到 return 就會中斷該函式。

function calcBmi(heightNum, weightNum) {
  let bmi = (weightNum / (((heightNum / 100) * heightNum) / 100)).toFixed(2);
  return bmi;
  console.log("123456789"); //不會執行
}
let shannonBmi = calcBmi(168, 55);

這樣子是不是代表整個函式只能寫一個 return 呢?其實不是的!

讓我們看看以下的範例會更清楚:

function add(num1, num2) {
  if (num1 < 0 && num2 < 0) {
    return 0; //當符合 if 條件時執行此 return 後並中斷函式
  } else {
    return num1 + num2; //當不符合 if 條件時執行此 return 後並中斷函式
  }
  console.log("123"); //都不會執行到
}

return 其實可以設定多組,但要特別留意的地方在函式內只要執行了一次 return 就會中斷該函式。

那如果我們什麼值都不 return 還會中斷函式嗎?

function add(num1, num2) {
  return;
  console.log("123"); //沒有執行
}

return 還是有中斷函式的效果。

最後來聊一個跟 return 有關聯性的東西自動插入分號(automatic semicolon insertion,ASI), 自動插入分號是什麼意思呢?

return 來舉例好了!

如果我們今天想 return num1+num2 ,但不小心斷行了,會發現:

function add (num1,num2){
	return
	num1+num2;
}
let shannonNum = add (1,2);
console.log(shannonNum)//undefined

為什麼 shannonNum 居然變成 undefined 了!

那是因為 return 會被自動插入分號,所以其實執行時長這樣:

function add(num1, num2) {
  return;
  num1 + num2;
}
let shannonNum = add(1, 2);
console.log(shannonNum); //undefined

那當然就被中斷而沒有回傳值出去,所以要特別留意 return 的斷行。

知識點:return

  • 可透過 return 回傳值並將值賦予到變數上
  • 函式只要執行到一次 return 就會被中斷
  • return 即使不回傳值一樣能中斷函式
  • 要留意 return 會受自動插入分號的影響

總結

  • 函式的組成包含:名稱、參數、想執行的程式碼,要執行時需呼叫函式
  • 參數間透過 , 逗號區隔,且可自定義名稱,也可自定義預設值
  • 想回傳函式的值可以透過 return ,只要執行一次 return 就會中斷函式

小練習

1.請問以下關於函式的敘述何者錯誤?
A 參數名稱可以自定義,並可給予預設值
B 想回傳函式內的值可以透過 return
C 函式可以不用呼叫也會自動執行
D 執行到一次 return 就會中斷該函式

解答:函式需要透過呼叫才能執行,選項 C 錯誤。

2.請參考以下程式碼,選出錯誤敘述的選項

function add(num1, num2 = 1) {
  return num1 + num2;
  console.log("123");//選項一
}
let numA = add(1);
console.log(numA);//選項二
let numB = add(1, 3);
console.log(numB);//選項三

A 選項一不會執行,因為 return 中斷函式了
B 選項二因為 numA 呼叫時沒有帶入第二個參數,所以會印出 NaN
C 選項三會印出 4
D 範例程式碼的函式為函式陳述式

解答:參數 num2 有帶入預設值 1 ,呼叫時未給予值會帶入預設值,所以選項二會印出 2 ,選項 B 錯誤。


參考文獻

JavaScript 必修篇 - 前端修練全攻略(六角學院)
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Guide/Functions
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/return


上一篇
入門魔法 - 物件
下一篇
入門魔法 - 了解 JSON 格式及內建方法
系列文
JavaScript 魔法入門 - 從入門到中階觀念30

尚未有邦友留言

立即登入留言