JAVASCRIPT V2 · EVERYDAY · 58
Array Methods:不是背 API,而是選對 Collection Operation
你已經會用 loop 逐筆處理資料。現在要學的是用 method 表達「這一步到底在轉換、篩選、查找、判斷還是累積」。重點是 callback contract、input/output shape 與 mutation,而不是把 code 寫得最短。
Learning outcomes
- 依問題選擇
map/filter/find/some/every/reduce。 - 逐輪 trace callback input 與 return value。
- 理解每個 method 的 result shape。
- 區分 non-mutating pipeline 與 mutating operations。
- 能把多步 transform 拆成可 debug 的 stages。
1. Why now:Loop 能做,但 intent 不一定清楚
const names = [];
for (const student of students) {
names.push(student.name);
}
這完全正確。map 的價值不是「loop 很舊」,而是它直接說:每筆 input 會產生一筆 output。
2. Callback contract:method 會反覆呼叫你的 function
students.map(student => student.name);
理解 callback 是後面 event handler、Promise、higher-order function 的重要基礎。
3. Worked Example A:map 改變 shape,不改變筆數
const students = [
{ name: "Amy", score: 92 },
{ name: "Bob", score: 58 }
];
const names =
students.map(
student => student.name
);
| callback input | callback return |
|---|---|
| {Amy,92} | "Amy" |
| {Bob,58} | "Bob" |
shape:Student[] → string[],length 仍然是 2。
4. filter:callback 回 Boolean,決定保留誰
const passed =
students.filter(
student => student.score >= 60
);
shape 仍是 Student[],但筆數可能變少。callback 的 return 不是「新的元素」,而是 keep/drop decision。
5. find、some、every 問的是不同問題
| Method | 問題 | Result |
|---|---|---|
find | 第一個符合的是誰? | element / undefined |
some | 至少有一個符合? | boolean |
every | 全部都符合? | boolean |
students.find(s => s.name === "Bob");
students.some(s => s.score < 60);
students.every(s => s.score >= 0);6. Worked Example B:不要用 filter 回答 yes/no
// 比較繞
const hasFailed =
students.filter(s => s.score < 60)
.length > 0;
// 更直接
const hasFailed =
students.some(s => s.score < 60);
選 method 的第一個標準是「你的問題是什麼」,不是哪個 API 比較熟。
7. reduce:把很多 elements 累積成另一種 result
const total =
students.reduce(
(sum, student) =>
sum + student.score,
0
);
| iteration | sum before | score | return next sum |
|---|---|---|---|
| Amy | 0 | 92 | 92 |
| Bob | 92 | 58 | 150 |
initial accumulator 很重要,尤其空 array。沒有明確理由時,不要為了炫技把簡單 loop 強改成複雜 reduce。
8. Method chain:每一步都要能說出 shape
const passedNames =
students
.filter(s => s.score >= 60)
.map(s => s.name);
Debug chain 時,先拆成中間變數確認每一步 result shape,再重新 chain。
9. Missing return 是 callback 高頻 bug
const doubled = [1, 2, 3].map(n => {
n * 2;
});
console.log(doubled);
// [undefined, undefined, undefined]
有大括號的 arrow function 不會自動 return expression。
10. Mutation:Array method 並不全部是 immutable
const values = [3, 1, 2];
values.sort();
console.log(values); // 原 array 被改
map/filter 會建立新 array;sort/push/splice 等會修改原 array。使用前要知道 reference 是否被其他 code 共用。
11. Worked Example C:Statistics pipeline
const valid =
students.filter(
s => s.score >= 0 && s.score <= 100
);
const average =
valid.length === 0
? 0
: valid.reduce(
(sum, s) => sum + s.score,
0
) / valid.length;
先 filter data quality,再 aggregate。每一步責任比「一個超大 reduce」更清楚。
12. Common mistakes
A. map callback 忘記 return
得到 undefined array。
B. find 找不到後直接讀 property
students.find(...).name // 可能 TypeError
C. 用 filter 只為了 yes/no
優先考慮 some/every。
D. reduce 沒有 initial value
空 array 可能直接 throw;accumulator type 也更難推理。
13. Debug evidence:拆 chain 看每個 shape
const passed =
students.filter(s => s.score >= 60);
console.table(passed);
const names =
passed.map(s => s.name);
console.log(names);
「哪一步 shape 開始不對」通常比盯著最後一行更容易定位。
14. Guided exercise:選 method,不急著寫 code
- 取得所有名字 → ?
- 保留及格學生 → ?
- 找 id=7 → ?
- 至少一個滿分 → ?
- 全部 score 合法 → ?
- 總分 → ?
15. Independent exercise:passingNames(students)
先 filter score >= 60,再 map 成 name。測混合成績、剛好 60、全部不及格、空 array。
16. Challenge:把 pipeline 拆成可解釋的 stages
輸入 Student[],輸出「及格且名字排序後」的 string[]。你要能寫出每一步 shape,而不是只交一行 chain。
Project checkpoint:Grade Tracker Statistics
function summarize(students) {
const passed =
students.filter(s => s.score >= 60);
const total =
students.reduce(
(sum, s) => sum + s.score,
0
);
return {
passedCount: passed.length,
average:
students.length
? total / students.length
: 0,
hasPerfect:
students.some(s => s.score === 100)
};
}17. Vocabulary / Summary
- callback:被另一個 function/method 呼叫的 function。
- predicate:回 Boolean 的條件 function。
- pipeline:多個 transformation/selection steps 串接。
- shape:資料在每一步的結構,例如 Student[] → string[]。
- accumulator:reduce 用來累積結果的 state。
18. Further reading
Knowledge check
- 說明 map/filter/find/some/every/reduce 各自回答什麼問題。
- trace filter → map 的 shape。
- 解釋 callback 忘記 return 為何會得到 undefined。
- 舉出一個會 mutate 原 array 的 method。
- 完成
passingNames()mastery tests。