【JS 專案 - 02】 為你的 TodoList 加點函數小菜


Posted by nancy543 on 2021-04-14

接著來到 TodoList v2.0,今天我們來加點函數小菜!
在這可能就有很多初學者跟我一樣的黑人問號??!!

Q1:什麼是函數?什麼是函式?
A1:接下來本篇會教到一個新的名詞和用法,也就是 Function ,台灣翻譯叫「函數」、大陸翻譯「函式」,這裡我們統一以台灣版翻譯為主。

Q2:為何要使用函數(Function)?
A2:大部分的專案裡面都會存在著很多重複性的步驟,以 TodoList 來說:
今天上午新增一個 A、B、C 事項,然後下午修改了 B 事項,後來 A 事項被取消了,所以刪除。隔天在新增 D、E 事項,接著不久又修改 C、D 事項和刪除 E 事項。

(這時候就會看到工程師的經典表情...)
工程師表情包

不論上述事項怎麼增增減減或修改,都還是依循著上一篇提到的5大主功能(儲存、顯示、新增、修改、刪除)在運作,只是把運作中的主角換掉。

如果用原先的程式碼來處理上述的工作,那工程師們可能都想撞牆了,因為都是一堆重複性的工作,無限的複製貼上,程式碼也不知道會爆出幾百幾千行,更別說超難維護與除錯的肥大檔案會造成網頁多大的負擔。既然重工在工程師們的眼裡是個毒瘤,那麼可以解救這些悲慘工程師來處理這些重複性的工作,就是非 Function(函數) 莫屬了。

函數是構成 javascript的基本要素之一。一個函數本身就是一段 JavaScript程式,包含用於執行某一個任務或計算的語法。要呼叫某一個函數之前,你必須先在這個函數想要執行的 scope 中定義它。

簡單來說:
就是把一段或多段的重複指令包起來,等到需要的時候呼叫它,以方便重複執行相同的任務。

所以本篇的學習重點,就是把上一篇的指令全部函數化之後,再呼叫執行而已。


Function(函數) 的宣告方法有好幾種

  1. 函數宣告 Function Declaration
  2. 函數運算式 Function Expression
  3. 函數關鍵字 Function Keyword

這裡僅先以「函數宣告 Function Declaration」來使用和解說,若有興趣研究其他方法的同學請往這走,或是直接拉到文章最下方也有推薦參考文 ↓↓↓↓↓

函數宣告寫法:

function myFunction(){
    .....
}

function 函數名稱 (參數1, 參數2, 參數3, ...) {
  // 要執行的程式代碼
  // 返回值 return
}

JS 白話文:

  • function 來宣告一個函數,後面加上自取的函數名稱(如:myFunctionmyName...)。當然函數也可以沒有名稱,只是寫法不是這樣。沒有名字的函數在 JS 是合法的,通常我們稱它為「匿名函數」,這個暫時不是本文的討論範圍,以後等我心情好XD有空就會另寫一篇關於函數的詳細討論。
  • 小括號 () 中的內容,稱為參數(function parameters),多個參數則用逗號 , 隔開。如果不需要參數,小括號內空白就好,但不可省略,例:function myName()
  • 大括號 {} 內的內容,則是要執行的程式代碼,可用 return 這個功能,來返回指定的值給調用的參數,同時程式也會停止繼續執行,若不用 return 的話則會返回 undefined

說了一堆聽不懂的,還是來個範例比較好理解。下方是早餐店漢堡的食譜,我們寫成函數試試看:

//牛肉漢堡
function HamburgerWithBeef(){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add Beef'; //第三步:牛肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

換成豬肉漢堡試試看:

//豬肉漢堡
function HamburgerWithPork(){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add Pork'; //第三步:豬肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

再換成雞肉漢堡:

//雞肉漢堡
function HamburgerWithChicken(){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add Chicken'; //第三步:雞肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

買尬!如果你是老闆,會不會覺得怎麼那麼煩,有夠多重複的工作方式,如果來個機器人員工幫忙製作就好了...

沒錯,函數就是來解決老闆們的煩惱,讓我們先找出哪裡不一樣!
看來似乎都是肉肉搞的鬼,這些要替換的肉類其實就是我們上面所講到的「參數(function parameters)」,但是參數要放在小括號裡面阿,所以我們稍微修改一下程式內容,把會變動的字改放到小括號內,我們取個參數名叫 meat 好了。

function HamburgerWith(meat){
    step1 = 'get one bread'; //第一步:放一片麵包
    step2 = 'add Cheese'; //第二步:加起司
    step3 = 'add' + meat; //第三步:肉肉放起來
    step4 = 'put a pice of bread on top'; //第四步:再放一片麵包在上面
}

宣告完啦!就這麼簡單幾句就可以完成製作各種漢堡的統一條件,但...這只是做完漢堡而已,都還沒到客人手中啊,這時就要用到 呼叫函數 來出餐了。


呼叫函數(Calling function)

宣告完的函數並不會自動的執行,你必須呼叫函數,才會執行函數的內容。

寫法:
函數名稱(參數);

所以做完的漢堡出餐的執行方式就會是這樣...

HamburgerWith(Beef); //牛肉漢堡
HamburgerWith(Pork); //豬肉漢堡
HamburgerWith(Chicken); //雞肉漢堡

以上就是函數的概念,是不是簡單很多。
回到我們的 TodoList 專案,v2.0 版就是把上一篇寫的 code 全部函數化,以方便呼叫重複執行的指令。

先回憶一下上一版 v1.0 的 TodoList 長這樣:

// 1.儲存代辦清單內的陣列資料
var todos = ['item1','item2','item3'];

// 2.顯示代辦清單
console.log(todos);

// 3.新增新的項目
todos.push('newItem');

// 4.更改陣列內的值
todos[0] = 'updated';

// 5.刪除項目
todos.splice(2, 1);

修改為函數化寫法:

1. 儲存代辦清單:
因為是宣告所有的代辦清單,所以這行不用動


2. 顯示代辦清單:

function showTodos() {
    console.log('My todos: ', todos);
};

JS 白話文:

  • 取名一個函數名 showTodos,此項還用不到參數,所以小括號內容空白就好 ()
  • console.log 的內容稍微美化一下,改放字串 'My todos: ' 和變數名 todos,主要是為了讓最後印出的資料看起來更好理解

呼叫函數

showTodos();
  • 因沒設定參數,所以後方的小括號 ();保持空白
  • 印出 My todos: ['item1','item2','item3']

3. 新增新的項目:

function addTodos(newTodos) {
    myTodos.push(newTodos);
    showTodos();
};

JS 白話文:

  • 取名一個函數名 addTodos,小括號內的參數先保持空白(),等下再回頭處理它。
  • 把「1.新增項目」的 myTodos.push('new item'); 那行搬過來。小括號內 'new item' 是會隨著新增的名稱而任意變動,所以並不能以固定字串呈現,所以改為變數並取名為 newTodos。(注意:變數名稱不可加上單引號或雙引號,否則又會變回字串。)
  • 回到上一行 function addTodos(),小括號內的參數要填入剛剛的變數 newTodos,這樣函數內外都有相同變數名稱,才能取值調用,並正確執行函數內容。
  • 下一行加上 showTodos(); 來執行上面的程式。

呼叫函數

addTodos('do my homework');
  • 小括號內並寫入要新增的項目名稱,如'do my homework'
  • 印出 My todos: ['item1','item2','item3', 'do my homework'],可以發現最後面被添加了新的項目 'do my homework'

4. 更改陣列內的值:

function changeTodo (position, updatedName) {
    todos[position] = updatedName;
    showTodos();
};

JS 白話文:

  • 同樣我們並不知道使用者想要修改第幾個代辦事項或改成什麼名稱,於是 function 後的小括號內 2個參數,都要改為變數,參數1(修改位置)取名為 position。參數2(修改後的名稱)取名為 updatedName
  • 把「4.更改陣列」 todos[0] = 'updated'; 那行搬過來。中括號 [0] 內指的是修改位置,和上方的參數1 position 相同,接著 =右方是修改後名稱,也和上方參數2 updatedName相同,這樣才可正確的取到值並調用修改原有的清單項目內容。
  • 下一行加上 showTodos(); 執行程式。

呼叫函數

changeTodo(1, 'take a rest');
  • 小括號內並寫入參數,參數一是數字 1(指的是第二個位置的清單項目 'item2'),參數二是修改後名稱,如 'take a rest.'
  • 如果用 console.log 則印出 My todos: ['item1','take a rest','item3', 'do my homework'],可以發現第二項的 'item2' 已經被修改為 'take a rest'

5. 刪除項目:

function deleteTodo(position) {
    todos.splice(position, 1);
    showTodos();
};

先回憶一下Array的刪除指令用法 .splice(index, howmany, item1, ....., itemX),小括號內包含了:
1.第一個參數 index(必填):指定新增或刪除的序列號碼
2.第二個參數 howmany(選填):從指定新增或刪除的位置起算,共要移除幾筆資料
3.第三個參數 item1,.....,itemX(選填):為新增或修改後的內容(字串要加上單或雙引號),這裡不需要所以不填

JS 白話文:

  • 因為是刪除清單項目,這裡函數 function 的小括號 (),只需要第一個參數值,也就是變數 position,因為沒有要修改或異動項目名稱,當然也就不需要參數2,
  • 為了可以正確取到變數 position 的值,在使用刪除指令時, .splice() 的第 1個參數,就填入這個變數 position,而不是清單項目的位置。
  • 而第二個參數就維持數字 1 不變,因為目前一次只會刪除一個代辦事項。
  • 第三個參數一樣不需要新增或修改,所以不填。
  • 下一行加上 showTodos(); 執行程式。

呼叫函數

deleteTodo(0);
  • 小括號內並寫入參數 0 (指的是刪除第一個位置的清單項目)
  • 如果用 console.log 則印出 My todos: ['take a rest','item3', 'do my homework'] ,可以發現第一項的 'item1' 已經不見了。

終於結束了鬼打牆的程式解說,一樣幫各位統整一下剛剛 v2.0 的程式碼

// 1.儲存代辦清單內的陣列資料
var todos = ['item1','item2','item3'];

// 2.顯示代辦清單
function showTodos() {
    console.log('My todos: ', todos);
};

// 3.新增新的項目
function addTodos(newTodos) {
    myTodos.push(newTodos);
    showTodos();
};

// 4.更改陣列內的值
function changeTodo (position, updatedName) {
    todos[position] = updatedName;
    showTodos();
};

// 5.刪除項目
function deleteTodo(position) {
    todos.splice(position, 1);
    showTodos();
};

這篇我們學習到具名函數的結構和表達方式,以及如何取值調用。不過這裡只是函數領域的冰山一角,它還有很多更細節的領域可以去探索。本文僅提供施作 ToDoList 專案的功能代碼介紹而已,不多詳加贅述關於函數的其他功能,如果你有興趣,可以看下方的參考資料,或是多去爬文了解,也許可以更帶領你增進許多關於函數的知識。

感謝你耐心看完本文,請到後台跟我領取乖寶寶貼紙一枚 =3= 啾

本文學習參考資料:


#javascript #js #todolist #note #初心者







Related Posts

網際網路是什麼?

網際網路是什麼?

EsLint 我們重頭來過吧

EsLint 我們重頭來過吧

PHP會員管理系統 - 註冊表單判斷

PHP會員管理系統 - 註冊表單判斷


Comments