Skip to content

Commit c97b768

Browse files
committed
完成4個實作筆記
1 parent cd2b1f0 commit c97b768

File tree

6 files changed

+521
-6
lines changed

6 files changed

+521
-6
lines changed

AI生成_基礎筆記/03_核心操作.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ console.log(passed); // Output: [85, 78, 90]
8585
8686
// (補充) 原始陣列保持原樣
8787
console.log(scores); // Output: [85, 42, 78, 90, 55]
88-
8988
```
9089
9190
> **💡 React 應用:** 實作「刪除」功能。要刪除 ID 為 5 的項目,其實是「保留 ID **不等於** 5 的所有項目」。
@@ -197,7 +196,6 @@ const total = cart.reduce((acc, current) => {
197196

198197
// 3. 輸出結果
199198
console.log(total); // Output: 150
200-
201199
```
202200
203201
---
@@ -276,7 +274,6 @@ const {
276274
// 現在可以直接使用變數,不需要再寫 user.name 了
277275
console.log(name, age, role);
278276
// Output: Willy 25 Admin
279-
280277
```
281278
282279
#### 🔑 核心觀念重點整理
@@ -317,7 +314,6 @@ const coordinates = [121.5, 25.0];
317314
const [lng, lat] = coordinates;
318315

319316
console.log(lng); // 121.5
320-
321317
```
322318
323319
> **💡 React 應用:** `useState` Hook 的基礎。
@@ -340,7 +336,6 @@ const newItem = 4;
340336
// ✅ 正確:創造新陣列,包含舊資料 + 新資料
341337
const newList = [...oldList, newItem];
342338
console.log(newList); // [1, 2, 3, 4]
343-
344339
```
345340
346341
### 展開物件
@@ -355,7 +350,6 @@ const updatedUser = { ...user, age: 26 };
355350

356351
console.log(updatedUser); // { name: "Willy", age: 26 }
357352
// 原本的 user 物件完全沒變 (Immutability)
358-
359353
```
360354
361355
---
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
### 實戰一:DOM 操作與事件監聽入門 ——「黃綠紅選色器」
2+
3+
* **對應專案**`CodeShiba/01 Color`
4+
* **專案目標**:做一個能切換標題、點擊色塊會顯示對應顏色的互動網頁。
5+
6+
#### 1. 抓取 HTML 元素 (DOM Selection)
7+
8+
要操作網頁上的元素,第一步就是把它們「抓」進 JavaScript 裡。
9+
10+
* **`getElementById`**:抓取「唯一」的元素 (ID 是身分證)。
11+
> 範例:抓取切換按鈕與標題區塊。
12+
13+
14+
```javascript
15+
const changeTitleButton = document.getElementById('changeButton')
16+
let titleDiv = document.getElementById('title')
17+
```
18+
19+
20+
* **`querySelectorAll`**:一次抓取「多個」類似的元素 (Class 是制服)。
21+
> 範例:抓取所有 class 為 `.colorSquare` 的色塊按鈕,這會回傳一個 NodeList (類似陣列)。
22+
23+
24+
```javascript
25+
const squares = document.querySelectorAll('.colorSquare')
26+
```
27+
28+
29+
30+
#### 2. 事件監聽 (Event Listeners)
31+
32+
抓到元素後,我們要告訴程式:「當使用者做了什麼動作 (Event),你要做什麼反應」。
33+
34+
* **方法 A:`addEventListener` (標準寫法)**
35+
> 這是最正規的寫法,適合綁定複雜邏輯。範例中用來綁定點擊事件 (`click`) 到 `changeTitle` 函式。
36+
37+
38+
```javascript
39+
// 當 changeTitleButton 被 "click" 時,執行 changeTitle
40+
changeTitleButton.addEventListener("click", changeTitle);
41+
```
42+
43+
44+
* **方法 B:`.onclick` (簡潔寫法)**
45+
> 適合簡單的邏輯綁定。範例中用箭頭函式直接定義點擊後的行為。
46+
47+
48+
```javascript
49+
// 綁定 reset 事件
50+
resetGameBtn.onclick = () => resetScore()
51+
```
52+
53+
54+
55+
#### 3. 批次處理 (ForEach Loop)
56+
57+
當我們用 `querySelectorAll` 抓到一堆按鈕時,不可能一個一個去寫 `onclick`。這時 `forEach` 就派上用場了。
58+
59+
> **核心觀念**:只要寫一次邏輯,就能套用到所有按鈕上。
60+
61+
```javascript
62+
// squares 裡面有紅、黃、綠三個按鈕
63+
squares.forEach(square => {
64+
// 對每一個 square (按鈕) 綁定 onclick
65+
square.onclick = () => {
66+
// 取得被點擊按鈕的 id (例如 'red')
67+
_id = square.getAttribute('id')
68+
// ...顯示結果
69+
}
70+
})
71+
```
72+
73+
#### 4. 修改內容與樣式 (Content & Style)
74+
75+
互動的最後一步,就是將結果「顯示」給使用者看。
76+
77+
* **修改 HTML 內容 (`innerHTML`)**
78+
> 可以放入純文字,也可以放入 HTML 標籤。
79+
80+
81+
```javascript
82+
// 使用樣板字面值動態生成 HTML
83+
output.innerHTML = `<div class='colorSquare' id='${_id}'><p>你點到了: ${_id}</p></div>`
84+
```
85+
86+
87+
* **修改 CSS 樣式 (`style`)**
88+
> 直接透過 JS 改變元素的外觀。
89+
90+
91+
```javascript
92+
// 把標題文字變成藍色
93+
titleDiv.style.color = `blue`
94+
```
95+
96+
---
97+
98+
**💡 實戰一總結:**
99+
這個練習讓我們習慣了 **「選取元素 (`querySelector`) -> 綁定事件 (`onclick`) -> 修改狀態 (`innerHTML/style`)」** 這樣的標準前端開發流程。
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
### 實戰二:計時器與狀態管理 ——「JS 碼錶」
2+
3+
* **對應專案**`CodeShiba/02 stopwatch`
4+
* **專案目標**:製作一個可以開始、暫停、重置的碼錶,精準到毫秒。
5+
6+
#### 1. 時間控制核心 (SetInterval & ClearInterval)
7+
8+
JavaScript 的時間不是連續流動的,而是透過「每隔多久執行一次函式」來模擬。
9+
10+
* **啟動計時 (`setInterval`)**
11+
> 設定一個鬧鐘,每隔 10 毫秒就呼叫一次 `timer()` 函式。注意要將回傳的 ID 存入變數 (`interval`),這樣之後才能找到它並關掉。
12+
13+
14+
```javascript
15+
let interval = null; // 用來存放計時器的 ID
16+
17+
buttonStart.onclick = () => {
18+
// 重要檢查:如果 interval 是空的 (代表目前沒在跑),才啟動新的
19+
// 這防止了使用者狂按 Start 造成產生多個計時器疊加 (加速) 的 Bug
20+
if (!interval) {
21+
interval = setInterval(timer, 10);
22+
}
23+
}
24+
```
25+
26+
27+
* **停止計時 (`clearInterval`)**
28+
> 拿著剛剛存好的 ID (`interval`) 去取消鬧鐘。
29+
30+
31+
```javascript
32+
buttonStop.onclick = () => {
33+
if (interval) {
34+
clearInterval(interval); // 停止計時
35+
interval = null; // 歸零 ID,讓 Start 按鈕知道現在是停止狀態
36+
}
37+
}
38+
```
39+
40+
41+
42+
#### 2. 狀態變數管理 (State Management)
43+
44+
網頁上看到的數字只是「顯示結果」,真正的數據都存在 JavaScript 的變數裡。
45+
46+
* **定義狀態**
47+
> 我們需要變數來記住現在跑了幾秒、幾毫秒。
48+
49+
50+
```javascript
51+
let seconds = 0;
52+
let m_seconds = 0;
53+
```
54+
55+
56+
* **重置狀態 (Reset)**
57+
> 按下重置時,不只要把畫面歸零,更重要的是要把「背後的變數」也歸零,不然下次開始會從舊的時間繼續跑。
58+
59+
60+
```javascript
61+
buttonReset.onclick = () => {
62+
// 先停止計時
63+
if (interval) {
64+
clearInterval(interval);
65+
interval = null;
66+
}
67+
// 資料歸零
68+
seconds = 0;
69+
m_seconds = 0;
70+
// 畫面歸零
71+
displaySeconds.innerHTML = `00`;
72+
displayMSeconds.innerHTML = `00`;
73+
}
74+
```
75+
76+
77+
78+
#### 3. 邏輯判斷與補零 (String Formatting)
79+
80+
這是新手最容易卡關的地方:如何讓 `9` 變成 `09`?如何讓毫秒滿 100 進位?
81+
82+
* **進位邏輯**
83+
> `timer` 函式中,每次執行毫秒 `+1`,並檢查是否該進位。
84+
85+
86+
```javascript
87+
const timer = () => {
88+
m_seconds++;
89+
90+
// 進位檢查:如果毫秒超過 99
91+
if (m_seconds > 99) {
92+
m_seconds = 0; // 毫秒歸零
93+
seconds++; // 秒數加一
94+
// ...更新畫面
95+
}
96+
}
97+
```
98+
99+
100+
* **字串補零 (Padding)**
101+
> 為了美觀,當數字小於 10 時,我們手動在前面加字串 `"0"`
102+
103+
104+
```javascript
105+
if (Number(m_seconds) <= 9) {
106+
displayMSeconds.innerHTML = `0${m_seconds}`;
107+
}
108+
109+
if (Number(m_seconds) > 9) {
110+
displayMSeconds.innerHTML = m_seconds;
111+
}
112+
```
113+
114+
115+
116+
---
117+
118+
**💡 實戰二總結:**
119+
這個專案教會了我們 **「變數 (Model) 與 畫面 (View) 分離」** 的概念。我們修改的是變數 (`seconds`),然後再同步更新到畫面上。這是現代前端框架 (如 React/Vue) 的核心精神。
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
### 實戰三:遊戲邏輯與複雜判斷 ——「剪刀石頭布」
2+
3+
* **對應專案**`CodeShiba/03 paperscissorstone`
4+
* **專案目標**:製作一個能跟電腦對戰的猜拳遊戲,並即時顯示勝負結果。
5+
6+
#### 1. 隨機數的藝術 (Random Choice)
7+
8+
電腦要能隨機出拳,靠的是 JavaScript 內建的數學函式庫。
9+
10+
* **`Math.random()`**:產生 0 ~ 0.999... 之間的隨機小數。
11+
* **`Math.floor()`**:無條件捨去小數點,變成整數。
12+
13+
> **公式解析**`Math.random() * 3` 會得到 0 ~ 2.99... 的數,再用 `floor` 捨去,就剛好得到 `0, 1, 2` 這三個整數,完美對應陣列的索引 (Index)。
14+
15+
```javascript
16+
function getComputerChoice() {
17+
let pssChoices = ['Stone', 'Paper', 'Scissors'];
18+
// 隨機產生 0, 1, 2
19+
let randomIndex = Math.floor(Math.random() * 3);
20+
return pssChoices[randomIndex];
21+
}
22+
```
23+
24+
#### 2. 優雅的勝負判斷 (Object Lookup Table)
25+
26+
這是本專案最高級的技巧!新手通常會寫一大堆 `if (player=='Stone' && computer=='Scissors')`,寫起來又長又容易錯。
27+
28+
> **高手寫法**:建立一個「規則物件 (Lookup Table)」,定義「每個拳種會贏誰」。
29+
> 這樣程式碼只有三行判斷:
30+
> 1. 一樣 -> 平手 (`0`)
31+
> 2. 玩家的拳會贏電腦 -> 贏 (`1`)
32+
> 3. 剩下情況 -> 輸 (`-1`)
33+
34+
```javascript
35+
function getResult(playerChoice, computerChoice) {
36+
// 定義勝利規則:Key (贏家) -> Value (輸家)
37+
const rules = {
38+
'Stone': 'Scissors', // 石頭 贏 剪刀
39+
'Scissors': 'Paper', // 剪刀 贏 布
40+
'Paper': 'Stone' // 布 贏 石頭
41+
};
42+
43+
// 判斷邏輯
44+
if (playerChoice === computerChoice) return 0; // 平手
45+
46+
// 檢查:玩家出的拳 (key),對應到的輸家是否剛好是電腦 (value)?
47+
if (rules[playerChoice] === computerChoice) return 1; // 獲勝
48+
49+
return -1; // 否則就是輸
50+
}
51+
```
52+
53+
#### 3. 邏輯與畫面分離 (Separation of Concerns)
54+
55+
在這個專案中,程式碼被切分得很乾淨:
56+
57+
* **純計算 (Logic)**`getComputerChoice``getResult` 只負責算數學,完全不碰 HTML。
58+
* **純顯示 (DOM)**`showResult` 只負責把算好的分數拿來顯示,完全不管規則。
59+
* **控制器 (Controller)**`onClickPSS` 負責串接兩者。
60+
61+
```javascript
62+
function onClickPSS(playerChoice) {
63+
const computerChoice = getComputerChoice(); // 1. 產生數據
64+
const score = getResult(playerChoice, computerChoice); // 2. 計算結果
65+
showResult(score, playerChoice, computerChoice); // 3. 更新畫面
66+
}
67+
```
68+
69+
#### 4. 動態顯示結果 (Template Logic)
70+
71+
`showResult` 中,使用 `switch` 根據分數 (`-1, 0, 1`) 來決定顯示什麼文字,並利用樣板字面值將變數塞入句子中。記得要加上 `break` 來中斷 `switch` 喔!
72+
73+
```javascript
74+
switch (score) {
75+
case -1:
76+
result.innerText = `你輸了! 你出了${playerChoice},電腦出了${computerChoice}!`;
77+
break;
78+
// ... 其他 case
79+
}
80+
```
81+
82+
---
83+
84+
**💡 實戰三總結:**
85+
這個專案最大的收穫是學會了 **「用資料結構 (物件) 來簡化邏輯判斷」**。這招在未來處理複雜權限判斷或狀態對應時非常有用(例如:`statusMap = { 'pending': '等待中', 'success': '成功' }`)。

0 commit comments

Comments
 (0)