JavaScript 中的 map、filter 和 reduce:比較與教學
1. map():轉換每個元素
概念解釋:map() 就像是給陣列的每個元素「換裝」,它會依序對每個元素執行你提供的函數,然後把結果組成一個新陣列回傳。適合用在「轉換資料」的情境,例如把數字變成字串,或計算每個項目的新值。
優點:簡單、直覺,程式碼短小。 缺點:如果陣列很大,可能會產生多餘的中間陣列(但在現代瀏覽器中,效能通常沒問題)。
步驟教學:
-
步驟 1:建立一個陣列,例如 const numbers = [1, 2, 3, 4, 5];。
-
步驟 2:呼叫 map() 方法,裡面傳入一個箭頭函數(或傳統函數),函數接收每個元素(這裡叫 num),對它做轉換(例如乘以 2)。
-
步驟 3:把結果存到變數中,然後用 console.log() 印出來看。
-
步驟 4:在 Console 中執行,觀察結果是 [2, 4, 6, 8, 10]。
完整程式碼範例:
// 步驟 1: 建立陣列
const numbers = [1, 2, 3, 4, 5];
// 步驟 2 & 3: 使用 map 將每個數字乘以 2
const doubledNumbers = numbers.map(function(num) {
// 這裡是箭頭函數的傳統寫法,你也可以用箭頭函數簡寫:num => num * 2
return num * 2;
});
// 步驟 4: 印出結果
console.log('Map 結果:', doubledNumbers); // 輸出:Map 結果: [2, 4, 6, 8, 10]
實際應用情境:在 React 元件中,你可能用 map() 來渲染一個清單,例如把使用者資料轉成 JSX 元件。
2. filter():篩選元素
概念解釋:filter() 像是一道「過濾網」,它會檢查陣列的每個元素,符合條件的才留下,組成一個新陣列回傳。適合用在「挑選資料」的情境,例如找出偶數或特定條件的項目。
優點:邏輯清楚,容易讀懂篩選條件。 缺點:如果篩選條件複雜,函數內的邏輯可能變長。
步驟教學:
-
步驟 1:同樣用 const numbers = [1, 2, 3, 4, 5];。
-
步驟 2:呼叫 filter(),傳入一個函數,函數返回 true(留下)或 false(丟掉)。例如,檢查 num % 2 === 0(是否為偶數)。
-
步驟 3:存結果並印出。
-
步驟 4:執行後,結果是 [2, 4](只留下偶數)。
完整程式碼範例:
// 步驟 1: 建立陣列
const numbers = [1, 2, 3, 4, 5];
// 步驟 2 & 3: 使用 filter 篩選偶數
const evenNumbers = numbers.filter(function(num) {
// 這裡檢查 num 是否能被 2 整除,返回 true/false
return num % 2 === 0;
// 你也可以用箭頭函數簡寫:num => num % 2 === 0
});
// 步驟 4: 印出結果
console.log('Filter 結果:', evenNumbers); // 輸出:Filter 結果: [2, 4]
實際應用情境:在前端搜尋功能中,用 filter() 過濾出符合關鍵字的資料。
3. reduce():累積計算
概念解釋:reduce() 是「歸約」操作,它從陣列的第一個元素開始,逐步「累積」計算(用一個初始值),最後回傳一個單一值(不是陣列)。適合用在「彙總資料」的情境,例如求和、找最大值,或建構物件。
優點:功能強大,能處理複雜的累積邏輯。 缺點:初學者可能覺得抽象,需要多練習初始值和累加器的概念。
步驟教學:
-
步驟 1:建立陣列 const numbers = [1, 2, 3, 4, 5];。
-
步驟 2:呼叫 reduce(),傳入一個函數(兩個參數:acc 是累加器,num 是當前元素),和初始值(例如 0,用來求和)。
-
步驟 3:函數內更新 acc(例如 acc + num),最後 return acc。
-
步驟 4:執行後,結果是 15(1+2+3+4+5)。
完整程式碼範例:
// 步驟 1: 建立陣列
const numbers = [1, 2, 3, 4, 5];
// 步驟 2 & 3: 使用 reduce 計算總和
const sum = numbers.reduce(function(acc, num) {
// acc 是累加器,從初始值 0 開始
// 第一次:acc=0, num=1 → acc=1
// 第二次:acc=1, num=2 → acc=3
// ... 以此類推
return acc + num;
}, 0); // 第二個參數是初始值,預設是陣列第一個元素,但建議明確指定
// 步驟 4: 印出結果
console.log('Reduce 結果:', sum); // 輸出:Reduce 結果: 15
實際應用情境:計算購物車總金額,或在資料視覺化中彙總統計。
map vs. filter vs. reduce:快速比較表格
為了讓你更容易記住,我用表格整理它們的差異。記住,選擇哪個方法取決於你的需求:轉換用 map、篩選用 filter、累積用 reduce。
| 特性 | map() | filter() | reduce() |
|---|---|---|---|
| 主要用途 | 轉換每個元素(1:1 對應) | 篩選符合條件的元素(1:多) | 累積計算成單一值(多:1) |
| 回傳類型 | 新陣列(長度相同) | 新陣列(長度可能變短) | 單一值(數字、物件等) |
| 函數參數 | 單一元素(e.g., num) | 單一元素,返回 true/false | 累加器 (acc) + 元素 (num) + 初始值 |
| 範例結果 | [1,2,3] → [2,4,6] | [1,2,3] → [2] (偶數) | [1,2,3] → 6 (總和) |
| 效能考量 | 適合簡單轉換 | 適合資料過濾 | 適合彙總,避免多餘陣列 |
| 常見錯誤 | 忘記 return | 條件邏輯錯 | 初始值沒設,導致 undefined |