剛開始學程式時,從 HTML 一路往 JavaScript 學。
對我來說,HTML 相對容易理解,因為寫下:
<h1>Hello World</h1>
<button>新增</button>
畫面就真的會出現標題和按鈕。
但開始接觸 JavaScript 後,我很快遇到一個問題:
我知道每一行大概是什麼,卻不知道為什麼下一行要這樣寫。
那時候的我很習慣記「順序」。
先宣告變數
↓
找到畫面上的元素
↓
寫 function
↓
監聽 click
↓
處理資料
只要把這套順序記起來,下次應該就會寫了吧?
結果換一個題目,又卡住。
後來我才慢慢發現,程式碼並沒有一套固定的排列順序。
比起一直問:
「下一行要寫什麼?」
更重要的是先問:
「下一步需要發生什麼?」
假設今天要做一個非常簡單的備忘錄:
[ 買牛奶 ] [+]
買牛奶
寫鐵人賽
需求只有:
+
HTML:
<input id="memoInput" placeholder="輸入備忘錄" />
<button id="addBtn">+</button>
<ul id="memoList"></ul>
JavaScript:
const memoInput = document.querySelector("#memoInput");
const addBtn = document.querySelector("#addBtn");
const memoList = document.querySelector("#memoList");
const memos = [];
addBtn.addEventListener("click", () => {
const text = memoInput.value.trim();
if (!text) return;
memos.push(text);
const li = document.createElement("li");
li.textContent = text;
memoList.appendChild(li);
memoInput.value = "";
});
以前的我可能會直接從第一行開始:
querySelector 是什麼?
addEventListener 是什麼?
trim 是什麼?
push 又是什麼?
createElement 又是什麼?
每個單字都查完了,整段卻還是不一定看得懂。
現在我會先把 Code 放到旁邊,看需求本身:
使用者輸入「買牛奶」
↓
按下 +
↓
取得輸入內容
↓
放進 memos
↓
建立一個 li
↓
顯示到畫面
有了這條線,再回頭看程式碼就會容易很多。
例如:
addBtn.addEventListener("click", () => {
不是因為 JavaScript 規定「這裡一定要寫事件監聽」。
而是因為需求本來就是:
等使用者按下 +,才開始新增。
接著:
const text = memoInput.value.trim();
是因為我們需要知道使用者到底輸入了什麼。
trim() 則會移除字串前後的空白。
例如:
" Hello ".trim();
會得到:
Hello
但文字中間原本存在的空白並不會一起被刪掉。
再來:
memos.push(text);
代表把取得的文字加入 memos 這個 Array。
所以資料其實正在走:
input
↓
memoInput.value
↓
text
↓
memos
↓
畫面
這時候我就不需要死背:
value後面一定接push。
而是知道:
我要先取得資料,才能把資料存起來。
程式碼的順序開始有了「原因」。
遇到一個小功能時,我會先問四個問題:
① 誰觸發這件事?
② 資料從哪裡來?
③ 資料目前放在哪裡?
④ 最後怎麼影響畫面?
套回剛剛的備忘錄:
誰觸發?
→ 使用者點擊 +
資料從哪裡來?
→ memoInput.value
資料放在哪?
→ memos
畫面怎麼改?
→ 建立 li,再 append 到 memoList
這個方法後來進到 React 專案也還是很好用,只是問題會再多一點:
這個 Component 負責什麼?
↓
資料從 Props、State 還是 API 來?
↓
哪個 function 處理資料?
↓
誰發出 Request?
↓
Response 回來放在哪?
↓
畫面最後吃哪份資料?
以前我會從第一行一路往下讀。
現在則會先找出整個功能的骨架,再回到程式裡確認每一段到底負責什麼。
if、function、Array、Event、map()、forEach()……
這些基本語法當然還是需要理解。
但我現在比較不會:
看範例
↓
背整段 Code
↓
期待下一題長得一模一樣
而是:
理解需求
↓
拆出流程
↓
確認資料在哪
↓
找出什麼時候執行
↓
再使用適合的語法
所以以前我最常問的是:
「下一行要寫什麼?」
現在我比較常問:
「下一步需要發生什麼?」
對我來說,這是開始讀懂程式碼很重要的一個轉折。
不過目前這個備忘錄還藏著一個問題:
const memos = [];
我們明明已經把「買牛奶」放進去了。
如果現在重新整理網頁,資料還會在嗎?
下一篇就來看看:
JavaScript 變數、瀏覽器儲存和真正透過 API 存到後端的資料,到底差在哪裡。