|
|
7 months ago | |
|---|---|---|
| .. | ||
| README.md | 7 months ago | |
| assignment.md | 7 months ago | |
README.md
JavaScript 基礎:陣列與迴圈
Sketchnote 由 Tomomi Imura 製作
journey
title 你的陣列與迴圈歷險
section 陣列基礎
建立陣列: 5: 你
存取元素: 4: 你
陣列方法: 5: 你
section 迴圈精通
For 迴圈: 4: 你
While 迴圈: 5: 你
現代語法: 4: 你
section 資料處理
陣列 + 迴圈: 5: 你
實務應用: 4: 你
效能優化: 5: 你
課前測驗
你是否曾好奇網站如何追蹤購物車的商品或顯示你的好友列表?這正是陣列與迴圈派上用場的地方。陣列就像數位容器,可以容納多筆資訊;而迴圈則讓你有效率地處理這些資料,無需重複寫出相同的程式碼。
這兩個概念合起來構成了你程式處理資訊的基礎。你將學會如何從手動寫出每個步驟,進化到寫出智慧且高效率的程式碼,能快速處理數百甚至數千個項目。
在本課程結束時,你將明白如何用幾行程式碼完成複雜的資料工作。讓我們一起探索這些程式設計的必備概念。
🎥 點擊上方圖片觀看陣列與迴圈相關影片。
你也可以在 Microsoft Learn 上學習此課程!
mindmap
root((資料處理))
Arrays
Structure
方括號語法
從零開始的索引
動態大小
Operations
push/pop
shift/unshift
indexOf/includes
Types
數字陣列
字串陣列
混合類型
Loops
For Loops
計數迭代
陣列處理
可預測流程
While Loops
基於條件
不確定迭代數
使用者輸入
Modern Syntax
for...of
forEach
函數式方法
Applications
Data Analysis
統計
篩選
轉換
User Interfaces
列表
選單
圖庫
陣列
把陣列想像成數位檔案櫃 — 不是每個抽屜放一份文件,而是在一個結構化的容器中組織多個相關項目。用程式語言來說,陣列讓你能將多筆資訊存放在一個有序的整合包中。
無論你是在建立相片集、管理待辦清單,或追蹤遊戲高分,陣列都提供了資料組織的基礎。讓我們看看陣列的運作方式。
✅ 陣列就在你身邊!你能想到一個真實生活中的陣列例子嗎,例如太陽能板陣列?
建立陣列
建立陣列超簡單 — 用中括號就搞定!
// 空陣列 - 就像一個空的購物車等待放入商品
const myArray = [];
這裡發生了什麼?
你剛用中括號 [] 建立了一個空的容器,就像一個空的圖書架,可以放你想整理的任何書籍。
你也可以從一開始就填入初始值:
// 你們冰淇淋店的口味菜單
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
// 使用者的個人資料資訊(混合不同類型的資料)
const userData = ["John", 25, true, "developer"];
// 你最喜歡的課程的考試成績
const scores = [95, 87, 92, 78, 85];
注意事項:
- 你可以在同一陣列中存放文字、數字甚至真假值
- 用逗號分隔每個項目 — 超簡單!
- 陣列非常適合將相關資訊放在一起
flowchart LR
A["📦 陣列"] --> B["建立 [ ]"]
A --> C["儲存多個項目"]
A --> D["透過索引存取"]
B --> B1["const arr = []"]
B --> B2["const arr = [1,2,3]"]
C --> C1["數字"]
C --> C2["字串"]
C --> C3["布林值"]
C --> C4["混合類型"]
D --> D1["arr[0] = 第一個"]
D --> D2["arr[1] = 第二個"]
D --> D3["arr[2] = 第三個"]
E["📊 陣列索引"] --> E1["索引 0:第一個"]
E --> E2["索引 1:第二個"]
E --> E3["索引 2:第三個"]
E --> E4["索引 n-1:最後一個"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
陣列索引
這裡有件事一開始可能覺得奇怪:陣列的索引從 0 開始,而不是 1。這種從零開始的索引源自電腦記憶體的運作方式 — 這是從像 C 語言這樣早期程式語言開始的慣例。陣列中每個位置都有一個稱作 索引 的地址號。
| 索引 | 值 | 說明 |
|---|---|---|
| 0 | "Chocolate" | 第一個元素 |
| 1 | "Strawberry" | 第二個元素 |
| 2 | "Vanilla" | 第三個元素 |
| 3 | "Pistachio" | 第四個元素 |
| 4 | "Rocky Road" | 第五個元素 |
✅ 陣列從索引 0 開始讓你驚訝嗎?在有些程式語言裡索引是從 1 開始。這背後有段有趣的歷史,你可以在 維基百科 詳細閱讀。
存取陣列元素:
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
// 使用中括號表示法存取單一元素
console.log(iceCreamFlavors[0]); // "巧克力" - 第一個元素
console.log(iceCreamFlavors[2]); // "香草" - 第三個元素
console.log(iceCreamFlavors[4]); // "滿滿堅果冰淇淋" - 最後一個元素
拆解下面的流程:
- 用 中括號加索引存取元素
- 回傳 該位置存放的值
- 從 0 開始計數,第一個元素索引就是 0
修改陣列元素:
// 更改現有值
iceCreamFlavors[4] = "Butter Pecan";
console.log(iceCreamFlavors[4]); // 「奶油胡桃」
// 在末尾新增元素
iceCreamFlavors[5] = "Cookie Dough";
console.log(iceCreamFlavors[5]); // 「餅乾生麵團」
上述程式碼說明:
- 將 索引為 4 的元素從 "Rocky Road" 改為 "Butter Pecan"
- 新增 索引為 5 的元素 "Cookie Dough"
- 陣列長度 自動擴充以容納新加入的元素
陣列長度與常用方法
陣列附帶內建屬性與方法,可以讓資料操作更簡單。
取得陣列長度:
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
console.log(iceCreamFlavors.length); // 5
// 陣列變化時,長度會自動更新
iceCreamFlavors.push("Mint Chip");
console.log(iceCreamFlavors.length); // 6
重點提醒:
- 回傳 陣列中元素總數
- 會隨 新增或移除元素自動更新
- 用於 迴圈與驗證時提供動態計數
常用陣列方法:
const fruits = ["apple", "banana", "orange"];
// 新增元素
fruits.push("grape"); // 新增至末尾:["apple", "banana", "orange", "grape"]
fruits.unshift("strawberry"); // 新增至開頭:["strawberry", "apple", "banana", "orange", "grape"]
// 移除元素
const lastFruit = fruits.pop(); // 移除並回傳 "grape"
const firstFruit = fruits.shift(); // 移除並回傳 "strawberry"
// 查找元素
const index = fruits.indexOf("banana"); // 回傳 1("banana" 的位置)
const hasApple = fruits.includes("apple"); // 回傳 true
理解這些方法:
- 用
push()(尾部)與unshift()(頭部)新增元素 - 用
pop()(尾部)與shift()(頭部)移除元素 - 用
indexOf()查找元素,用includes()檢查是否存在 - 提供移除元素或索引位置等有用資訊
✅ 自己試試看!在瀏覽器的主控台建立並操作你自己的陣列。
🧠 陣列基礎檢測:資料組織
考考你對陣列的理解:
- 你覺得陣列為何從 0 開始計數,而不是 1?
- 如果嘗試存取不存在的索引(例如在 5 個元素的陣列中存取
arr[100])會怎樣? - 你能想到三個現實生活中會用到陣列的場景嗎?
stateDiagram-v2
[*] --> EmptyArray: const arr = []
EmptyArray --> WithItems: 新增元素
WithItems --> Accessing: 使用索引
Accessing --> Modifying: 修改值
Modifying --> Processing: 使用方法
WithItems --> WithItems: push(), unshift()
Processing --> Processing: pop(), shift()
note right of Accessing
零基索引
arr[0] = 第一個元素
end note
note right of Processing
內建方法
動態操作
end note
真實案例: 陣列在程式中無處不在!社群媒體動態、購物車、相片集、播放清單歌曲 — 幕後其實都是陣列!
迴圈
把迴圈想像成在查爾斯‧狄更斯小說中寫字懲罰的場景,學生得反覆在石板上抄寫字句。想像你可以簡單下指令「寫這句話 100 次」,程式就能自動完成。迴圈就是為你的程式碼做到這點。
迴圈就像有位不知疲倦的助理,可以無誤重複工作。無論你需要檢查購物車每個項目、或是顯示相簿中所有照片,迴圈都能有效率地處理重複動作。
JavaScript 提供多種迴圈供選擇。讓我們逐一檢視,並了解何時使用。
flowchart TD
A["🔄 迴圈類型"] --> B["For 迴圈"]
A --> C["While 迴圈"]
A --> D["For...of 迴圈"]
A --> E["forEach 方法"]
B --> B1["已知的迭代次數"]
B --> B2["基於計數器"]
B --> B3["for(init; condition; increment)"]
C --> C1["未知的迭代次數"]
C --> C2["基於條件"]
C --> C3["while(condition)"]
D --> D1["現代 ES6+"]
D --> D2["陣列迭代"]
D --> D3["for(item of array)"]
E --> E1["函式風格"]
E --> E2["陣列方法"]
E --> E3["array.forEach(callback)"]
F["⏰ 何時使用"] --> F1["For: 計數、索引"]
F --> F2["While: 使用者輸入、搜尋"]
F --> F3["For...of: 簡單迭代"]
F --> F4["forEach: 函式式程式設計"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
For 迴圈
for 迴圈就像設定計時器 — 你知道確切次數要讓事情發生。結構清楚且可預測,最適合操作陣列或需要計數的場合。
For 迴圈結構:
| 元件 | 目的 | 範例 |
|---|---|---|
| 初始化 | 設定起始點 | let i = 0 |
| 條件判斷 | 何時繼續 | i < 10 |
| 遞增 | 如何更新 | i++ |
// 從0數到9
for (let i = 0; i < 10; i++) {
console.log(`Count: ${i}`);
}
// 更實用的範例:處理分數
const testScores = [85, 92, 78, 96, 88];
for (let i = 0; i < testScores.length; i++) {
console.log(`Student ${i + 1}: ${testScores[i]}%`);
}
逐步說明:
- 在一開始 初始化計數器
i為 0 - 每次 執行前檢查條件
i < 10 - 當條件為真時 執行區塊程式
- 每次迴圈後 執行
i++使i加 1 - 當條件變假時(
i達 10)停止迴圈
✅ 在瀏覽器主控台執行此程式碼。修改計數器、條件或遞增表達式會怎樣?能讓它倒數運作,變成倒數計時嗎?
🗓️ For 迴圈精熟檢測:可控重複
評估你對 for 迴圈的理解:
- for 迴圈的三個部分是什麼?每個的功能為何?
- 如何讓迴圈從陣列尾端往前執行?
- 如果忘記遞增部分 (
i++) 會發生什麼?
flowchart TD
A["🚀 開始 For 迴圈"] --> B["初始化: let i = 0"]
B --> C{"條件: i < array.length?"}
C -->|true| D["執行程式區塊"]
D --> E["遞增: i++"]
E --> C
C -->|false| F["✅ 退出迴圈"]
G["📋 常見模式"] --> G1["for(let i=0; i<n; i++)"]
G --> G2["for(let i=n-1; i>=0; i--)"]
G --> G3["for(let i=0; i<arr.length; i+=2)"]
style A fill:#e3f2fd
style F fill:#e8f5e8
style G fill:#fff3e0
迴圈智慧: 當你知道確切重複次數時,for 迴圈是最佳選擇,也是處理陣列最常用的型態!
While 迴圈
while 迴圈就像說「持續做這件事直到...」— 你或許不知道會執行多少次,但知道何時停止。很適合問使用者輸入直到得到想要的資料,或搜尋資料直到找到目標。
While 迴圈特色:
- 只要條件為真 就繼續執行
- 需手動管理 計數器變數
- 每次迭代前 先檢查條件
- 若條件永遠真 有無限迴圈風險
// 基本計數範例
let i = 0;
while (i < 10) {
console.log(`While count: ${i}`);
i++; // 別忘了遞增!
}
// 更實用的範例:處理使用者輸入
let userInput = "";
let attempts = 0;
const maxAttempts = 3;
while (userInput !== "quit" && attempts < maxAttempts) {
userInput = prompt(`Enter 'quit' to exit (attempt ${attempts + 1}):`);
attempts++;
}
if (attempts >= maxAttempts) {
console.log("Maximum attempts reached!");
}
解讀範例:
- 手動管理 迴圈內的計數器
i - 遞增 計數器避免無限迴圈
- 展示 透過使用者輸入與嘗試限制的實際用法
- 內建 防止無限執行的安全機制
♾️ While 迴圈智慧檢測:基於條件的重複
測試你對 while 迴圈的了解:
- 使用 while 迴圈時主要風險是什麼?
- 何時會選擇 while 迴圈而非 for 迴圈?
- 如何避免無限迴圈?
flowchart LR
A["🔄 While 與 For"] --> B["While 迴圈"]
A --> C["For 迴圈"]
B --> B1["未知次數"]
B --> B2["條件驅動"]
B --> B3["使用者輸入、搜尋"]
B --> B4["⚠️ 風險:無限迴圈"]
C --> C1["已知次數"]
C --> C2["計數器驅動"]
C --> C3["陣列處理"]
C --> C4["✅ 安全:可預測結束"]
D["🛡️ 安全提示"] --> D1["務必修改條件變數"]
D --> D2["包含跳脫條件"]
D --> D3["設定最大迭代次數"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#ffebee
安全第一: While 迴圈功能強大,但需謹慎管理條件。務必確保條件會最終變成假值!
現代迴圈替代方案
JavaScript 提供現代迴圈語法,使程式碼更易讀且降低錯誤。
For...of 迴圈 (ES6+):
const colors = ["red", "green", "blue", "yellow"];
// 現代方法 - 更乾淨且更安全
for (const color of colors) {
console.log(`Color: ${color}`);
}
// 與傳統的 for 迴圈比較
for (let i = 0; i < colors.length; i++) {
console.log(`Color: ${colors[i]}`);
}
for...of 的主要優點:
- 免除 索引管理,減少 off-by-one 錯誤
- 直接取得 陣列元素
- 提升 程式碼可讀性,降低語法複雜度
forEach 方法:
const prices = [9.99, 15.50, 22.75, 8.25];
// 使用 forEach 來實現函數式編程風格
prices.forEach((price, index) => {
console.log(`Item ${index + 1}: $${price.toFixed(2)}`);
});
// 使用箭頭函數的 forEach 來進行簡單操作
prices.forEach(price => console.log(`Price: $${price}`));
關於 forEach 的重點:
- 為陣列每個元素 執行一段函式
- 提供 元素值與索引作為參數
- 無法提前停止(不同於傳統迴圈)
- 回傳 undefined(不會產生新陣列)
✅ 為何會選擇 for 迴圈而非 while 迴圈?在 StackOverflow 上有 1.7 萬人討論這話題,部分意見你可能會覺得有趣 觀看討論。
🎨 現代迴圈語法檢測:擁抱 ES6+
評估你對現代 JavaScript 的掌握度:
for...of相較於傳統 for 迴圈有什麼優點?- 在什麼時候你仍會偏好用傳統 for 迴圈?
forEach與map有什麼差異?
quadrantChart
title 迴圈選擇指南
x-axis 傳統 --> 現代
y-axis 簡單 --> 複雜
quadrant-1 現代 複雜
quadrant-2 傳統 複雜
quadrant-3 傳統 簡單
quadrant-4 現代 簡單
傳統 For: [0.2, 0.7]
While 迴圈: [0.3, 0.6]
For...of: [0.8, 0.3]
forEach: [0.9, 0.4]
陣列方法: [0.8, 0.8]
現代趨勢: ES6+ 的
for...of和forEach逐漸成為陣列遍歷首選,因為語法更簡潔且錯誤更少!
迴圈與陣列
陣列與迴圈結合可創造強大的資料處理能力。這對許多程式任務至關重要,從顯示清單到計算統計數據。
傳統陣列處理:
const iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
// 經典的 for 迴圈方法
for (let i = 0; i < iceCreamFlavors.length; i++) {
console.log(`Flavor ${i + 1}: ${iceCreamFlavors[i]}`);
}
// 現代的 for...of 方法
for (const flavor of iceCreamFlavors) {
console.log(`Available flavor: ${flavor}`);
}
理解不同方法:
- 用陣列長度屬性決定迴圈界限
- 傳統 for 迴圈用索引存取元素
- for...of 迴圈直接取得元素
- 每個元素只處理一次
實務資料處理範例:
const studentGrades = [85, 92, 78, 96, 88, 73, 89];
let total = 0;
let highestGrade = studentGrades[0];
let lowestGrade = studentGrades[0];
// 使用單一迴圈處理所有分數
for (let i = 0; i < studentGrades.length; i++) {
const grade = studentGrades[i];
total += grade;
if (grade > highestGrade) {
highestGrade = grade;
}
if (grade < lowestGrade) {
lowestGrade = grade;
}
}
const average = total / studentGrades.length;
console.log(`Average: ${average.toFixed(1)}`);
console.log(`Highest: ${highestGrade}`);
console.log(`Lowest: ${lowestGrade}`);
程式碼運作說明:
- 初始化統計變數,用於加總與極值追蹤
- 高效地遍歷每一個成績
- 累積成績總和計算平均
- 迴圈中同時記錄最高與最低分
- 迴圈結束時計算出最終統計數據
✅ 在瀏覽器主控台用自己建立的陣列練習迴圈處理。
flowchart TD
A["📦 陣列資料"] --> B["🔄 迴圈處理"]
B --> C["📈 結果"]
A1["[85, 92, 78, 96, 88]"] --> A
B --> B1["計算總和"]
B --> B2["尋找最小/最大值"]
B --> B3["計算條件數量"]
B --> B4["轉換資料"]
C --> C1["平均: 87.8"]
C --> C2["最高分: 96"]
C --> C3["及格人數: 5/5"]
C --> C4["字母等級"]
D["⚡ 處理模式"] --> D1["累加(總和)"]
D --> D2["比較(最小/最大)"]
D --> D3["過濾(條件)"]
D --> D4["映射(轉換)"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#f3e5f5
GitHub Copilot Agent 挑戰 🚀
使用 Agent 模式完成下列挑戰:
說明: 建立一個結合陣列與迴圈的綜合資料處理函式,分析資料集並產生有意義的洞察。
提示: 建立一個名為 analyzeGrades 的函式,接受一個學生成績物件陣列(每個物件包含姓名與分數屬性),返回一個統計物件,包含最高分、最低分、平均分、及格人數(分數 >= 70)和高於平均分的學生姓名陣列。你的解決方案中至少要使用兩種不同的迴圈類型。
在此了解更多關於 Agent 模式。
🚀 挑戰
JavaScript 提供了幾個現代陣列方法,可以取代特定任務的傳統迴圈。探索 forEach、for-of、map、filter 和 reduce。
你的挑戰: 使用至少三種不同的陣列方法重構學生分數範例。注意隨著現代 JavaScript 語法,程式碼變得更加精簡且易讀。
課後小考
複習與自學
JavaScript 的陣列附帶許多方法,在資料操作上非常有用。閱讀這些方法 並嘗試在你自己建立的陣列上使用它們(例如 push、pop、slice 和 splice)。
作業
📊 你的陣列與迴圈工具總結
graph TD
A["🎯 陣列與迴圈精通"] --> B["📦 陣列基礎"]
A --> C["🔄 迴圈類型"]
A --> D["🔗 資料處理"]
A --> E["🎨 現代技術"]
B --> B1["建立: [ ]"]
B --> B2["索引: arr[0]"]
B --> B3["方法: push, pop"]
B --> B4["屬性: length"]
C --> C1["For: 已知迭代次數"]
C --> C2["While: 條件控制"]
C --> C3["For...of: 直接存取"]
C --> C4["forEach: 函式式"]
D --> D1["統計計算"]
D --> D2["資料轉換"]
D --> D3["篩選與搜尋"]
D --> D4["即時處理"]
E --> E1["箭頭函式"]
E --> E2["方法串接"]
E --> E3["解構賦值"]
E --> E4["模板字面量"]
F["💡 主要優點"] --> F1["高效資料處理"]
F --> F2["減少程式碼重複"]
F --> F3["可擴展的解決方案"]
F --> F4["更簡潔的語法"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
🚀 你的陣列與迴圈精通時間表
⚡ 接下來 5 分鐘你可以做的事
- 建立你最喜愛電影的陣列並存取特定元素
- 寫一個從 1 數到 10 的 for 迴圈
- 嘗試課程中的現代陣列方法挑戰
- 在瀏覽器主控台練習陣列索引
🎯 這一小時內你可以完成的目標
- 完成課後小考,複習挑戰性的概念
- 建立來自 GitHub Copilot 挑戰的完整成績分析器
- 建立一個簡單的購物車,能新增和移除商品
- 練習不同迴圈類型間的轉換
- 嘗試使用
push、pop、slice和splice等陣列方法
📅 你這週的資料處理旅程
- 完成「陣列迴圈」作業並加入創意改良
- 使用陣列與迴圈建立待辦事項清單應用程式
- 建立一個簡單的數據統計計算器
- 練習使用 MDN 陣列方法
- 建立圖片庫或音樂播放清單介面
- 探索使用
map、filter和reduce的函式式程式設計
🌟 你這月的變革
- 精通高級陣列操作與效能優化
- 建立完整的資料視覺化儀表板
- 參與開源數據處理專案
- 用實際範例教導他人陣列與迴圈
- 建立可重用的個人資料處理函式庫
- 探索以陣列建構的演算法與資料結構
🏆 終極資料處理冠軍自我檢測
慶祝你對陣列與迴圈的精通:
- 你學到的陣列操作中,哪項對真實世界應用最有用?
- 哪種迴圈類型你覺得最自然?為什麼?
- 理解陣列與迴圈後,你對組織資料的思考有何改變?
- 你接下來想挑戰什麼複雜的資料處理任務?
journey
title 你的資料處理演進
section 今天
陣列困惑: 3: 你
迴圈基礎: 4: 你
索引理解: 5: 你
section 本週
方法精通: 4: 你
高效處理: 5: 你
現代語法: 5: 你
section 下個月
複雜演算法: 5: 你
效能優化: 5: 你
教導他人: 5: 你
📦 你已經解鎖資料組織與處理的力量! 陣列與迴圈是你將建立的幾乎所有應用程式的基石。從簡單清單到複雜資料分析,你現在擁有有效且優雅處理資訊的工具。每個動態網站、行動應用和以資料為驅動的應用程式都依賴這些基本概念。歡迎來到可擴展資料處理的世界!🎉
免責聲明:
本文件由 AI 翻譯服務 Co-op Translator 翻譯而成。雖然我們致力於確保翻譯的準確性,但請注意自動翻譯可能包含錯誤或不精確之處。原文文件的母語版本應被視為權威來源。對於重要資訊,建議尋求專業人工翻譯。我們不對因使用本翻譯而產生的任何誤解或誤用承擔責任。


