← JavaScript Learning Path

JAVASCRIPT V2 · FOUNDATIONS · 40

Arrays、Objects、References:從幾個變數進入真正的資料模型

真實程式很少只有一個 score。你會有很多學生,每個學生又有 id、name、score。這一課的重點不是一次背完所有 array methods,而是先理解資料形狀、index、property、identity、reference 與 mutation。完整的 map/filter/find/reduce mastery 會放在 Stage 2 的 58。

Learning outcomes

1. Why now:五個學生不該變成十五個獨立變數

const name1 = "Amy";
const score1 = 92;
const name2 = "Bob";
const score2 = 58;

這種寫法無法自然擴充,也很難 loop。資料需要「一筆實體」與「多筆集合」兩個層級。

Object

一個實體,多個命名欄位。

Array

多筆同類資料,有順序。

2. Array basics:有順序的一串 values

const scores = [80, 90, 100];

console.log(scores[0]);     // 80
console.log(scores.length); // 3

Array index 從 0 開始。length 是 element 數量,不是最後一個 index。

const last =
  scores[scores.length - 1]; // 100

3. Array mutation:同一個 array state 可以改變

const scores = [80, 90];

scores.push(100);
scores[0] = 85;

console.log(scores); // [85, 90, 100]

const 阻止的是 binding reassignment,不是阻止 array 內容 mutation。這正好呼應 36。

4. Object basics:用 property 名稱描述一個 entity

const student = {
  id: 7,
  name: "Anson",
  score: 90
};

console.log(student.name);
student.score = 95;

Object 讓欄位有語意,不需要記「第二格代表姓名」。

5. Dot vs Bracket property access

student.name
student["name"]

const key = "score";
student[key]

已知固定 property name 時通常使用 dot notation;property name 來自變數時 bracket notation 很重要。

6. Worked Example A:Array of Objects 是常見 API 資料形狀

const students = [
  { id: 1, name: "Amy", score: 92 },
  { id: 2, name: "Bob", score: 58 },
  { id: 3, name: "Cara", score: 81 }
];

這種形狀會出現在 API JSON、database result、React list state。你應該能口頭描述:

students
= array
= 3 objects
= each object has id/name/score

7. Position vs Identity:index 不是資料 ID

students[0] // 現在第一個位置的資料
student.id  // 這筆資料自己的 identity

排序、filter、insert 後,某個 student 的 index 可能改變,但 id 通常仍用來辨認同一 entity。

這個區別到 React list key、database primary key 都非常重要。

8. Worked Example B:Loop + Object property

let total = 0;

for (const student of students) {
  total += student.score;
}

const average =
  students.length
    ? total / students.length
    : 0;

這裡直接組合前面三課:loop、function/data rule、object property。

9. Reference aliasing:兩個名稱可能指向同一個 object

const original = { score: 80 };
const alias = original;

alias.score = 100;

console.log(original.score); // 100

alias = original 沒有自動 clone object。兩個 bindings 都能存取同一個 object,因此 mutation 從另一個名稱也看得到。

10. Worked Example C:Shallow copy 建立另一個 top-level object

const original = {
  name: "Amy",
  score: 80
};

const updated = {
  ...original,
  score: 95
};

console.log(original.score); // 80
console.log(updated.score);  // 95

Spread 在這裡建立新的 top-level object。完整的 shallow/deep copy、nested object 問題會在 Stage 2/Advanced 再展開。

11. 找不到資料時,左邊 expression 可能是 undefined

const item = students[99];
console.log(item); // undefined

如果接著寫:

students[99].name
// TypeError

真正要 debug 的不是 .name 拼字,而是「students[99] 到底回了什麼」。

12. map/filter/find 先 Preview,不在這一課塞完

students.map(student => student.name);
students.filter(student => student.score >= 60);
students.find(student => student.id === 2);

現在只要知道它們各自表達不同的 collection operation。58 會逐步拆 callback、return shape、mutation 與 chaining。這是 v2 的粒度原則:不要一頁同時要求初學者 mastery 太多 abstraction。

13. Common mistakes

A. 把 length 當最後 index

scores[scores.length] // undefined

B. 把 index 當永久 identity

排序後 index 改變,不能假設「第 0 筆永遠是 Amy」。

C. 誤以為 assignment 會 clone object

const b = a; // alias,不是 clone

D. 在不知道資料存在時直接讀 property

先確認左邊 expression 的 value。

14. Debug evidence:先印 shape

console.log({
  isArray: Array.isArray(students),
  length: students.length,
  first: students[0]
});

console.table(students);

對陌生 API data,先確認「是不是 array、幾筆、第一筆有哪些 properties」,比直接猜 property path 有效。

15. Guided exercise:逐輪算 class average

const students = [
  { name: "A", score: 60 },
  { name: "B", score: 90 }
];

用 for...of 畫 trace:student、student.score、total before、total after。最後除以 students.length。

16. Independent exercise:實作 classAverage(students)

需求:

classAverage([]) // 0

classAverage([
  {score: 60},
  {score: 90}
]) // 75

17. Challenge:Alias bug

const a = { score: 80 };
const b = a;
b.score += 10;

先預測 a.score,再說明為什麼。如果你希望 b 是獨立 top-level object,要怎麼建立?

Project checkpoint:Grade Tracker Data Model

const students = [
  { id: 1, name: "Amy", score: 92 },
  { id: 2, name: "Bob", score: 58 },
  { id: 3, name: "Cara", score: 81 }
];

function classAverage(students) {
  if (students.length === 0) return 0;

  let total = 0;
  for (const student of students) {
    total += student.score;
  }
  return total / students.length;
}

Foundation 到這裡形成第一個完整鏈:value/type → condition → loop → function → data model。下一個 Stage 才進入常用 methods 與 modern syntax。

18. Vocabulary / Summary

19. Further reading

Knowledge check

  1. 解釋 array index 與 entity id 的差異。
  2. 說明 const b=a 為什麼不是 object clone。
  3. 指出 scores[scores.length] 為何是 undefined。
  4. 說明 Array of Objects 為何適合 API records。
  5. 完成 classAverage() mastery exercise並通過 empty/single/multiple tests。