← JavaScript Learning Path

JAVASCRIPT V2 · EVERYDAY · 58

Array Methods:不是背 API,而是選對 Collection Operation

你已經會用 loop 逐筆處理資料。現在要學的是用 method 表達「這一步到底在轉換、篩選、查找、判斷還是累積」。重點是 callback contract、input/output shape 與 mutation,而不是把 code 寫得最短。

Learning outcomes

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);
array method每個 elementcallbackreturnnew result

理解 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 inputcallback 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
  );
iterationsum beforescorereturn next sum
Amy09292
Bob9258150

initial accumulator 很重要,尤其空 array。沒有明確理由時,不要為了炫技把簡單 loop 強改成複雜 reduce。

8. Method chain:每一步都要能說出 shape

const passedNames =
  students
    .filter(s => s.score >= 60)
    .map(s => s.name);
Student[]filterStudent[]mapstring[]

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

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

18. Further reading

Knowledge check

  1. 說明 map/filter/find/some/every/reduce 各自回答什麼問題。
  2. trace filter → map 的 shape。
  3. 解釋 callback 忘記 return 為何會得到 undefined。
  4. 舉出一個會 mutate 原 array 的 method。
  5. 完成 passingNames() mastery tests。