JAVASCRIPT V2 · FOUNDATIONS · 36
Values、Variables、Types:程式真正保存的是什麼?
這不是一課把 let、const、typeof 背起來就結束。你要建立第一個可持續使用的 JavaScript runtime model:expression 產生 value、binding 讓名稱指向 value、type 影響後續 operator 的行為,而外部輸入常常需要明確轉型。
Learning outcomes
- 區分 literal、value、binding/identifier 與 type。
- 能逐行 trace assignment 前後的 value 與 type。
- 理解
const限制的是 binding reassignment,不是「世界上永遠不能變的資料」。 - 能用
typeof、Number()、Number.isNaN()蒐集型別 evidence。 - 遇到字串與數字混合 bug 時,先驗證 runtime value/type,而不是靠猜。
1. Why now:程式的下一步,都建立在「目前有哪些值」
假設我們要做 Grade Tracker。畫面上的名字、分數、是否及格,最後都必須先變成 JavaScript 可以處理的 value。
const studentName = "Anson";
let score = 90;
const passed = true;
這三行看起來簡單,但它們包含四個不同概念:
| 概念 | 例子 | 你應該問什麼 |
|---|---|---|
| literal | "Anson"、90、true | source code 怎麼直接寫出一個 value? |
| value | 字串 Anson、數字 90、Boolean true | runtime 現在真正要處理的資料是什麼? |
| binding / identifier | studentName、score | 後面的 code 用哪個名稱再次取得 value? |
| type | string、number、boolean | 這個 value 能參與哪些 operation? |
2. JavaScript 在哪裡做這些事?
在本站的 Browser JavaScript 練習裡,JavaScript engine 讀取程式碼並執行 expression。HTML 不會替你「執行變數」,GitHub 也不會替你決定 score + 5 的結果。
看到下面這一行時:
const total = 10 + 5;
- engine 先 evaluate
10 + 5。 - 得到 number value
15。 - 建立名稱
total。 - 讓
total取得這個 value。
先有 expression result,再有後續 state。這個思路到 function、Promise、React state 都還會用到。
3. Primitive values:先掌握最常遇到的五種
"Anson" // string
90 // number
true // boolean
undefined // undefined
null // null
| Type / value | 常見來源 | 常見錯誤 |
|---|---|---|
| string | input、URL、JSON 文字欄位 | 以為 "10" 已經是 number |
| number | 計算、座標、價格、分數 | 得到 NaN 卻繼續計算 |
| boolean | comparison、feature state | 把字串 "false" 當成 Boolean false |
| undefined | 沒有 return、找不到 property/result | 直接讀 undefined.name |
| null | 程式刻意表示「目前沒有值」 | 沒有先處理 absence |
typeof 是第一個 debugging probe:
console.log(score, typeof score);
它不是型別系統,但非常適合在初學階段確認「runtime 現在手上的東西到底是什麼」。
4. Worked Example A:let 是 state transition,不是裝飾
let score = 80;
score = 90;
score = score + 5;
| 執行完 | score | type | 發生什麼 |
|---|---|---|---|
| line 1 | 80 | number | 建立 binding |
| line 2 | 90 | number | reassignment |
| line 3 | 95 | number | 讀舊值、計算、再 assignment |
score = score + 5 不是數學等式。右邊先讀目前 value 並計算;最後才把結果重新指定給左邊的 binding。
5. const 真正限制的是 binding
const passingScore = 60;
// passingScore = 70;
// TypeError: Assignment to constant variable.
你不能讓 passingScore 重新指向另一個 value。這是初學時最重要的規則。
但之後學 object 時你會看到:
const settings = { theme: "dark" };
settings.theme = "light"; // 可以
因為 binding settings 沒有改成指向另一個 object;改的是 object 裡面的 property。這裡先知道差異即可,40 會正式處理 reference 與 mutation。
6. Worked Example B:為什麼畫面上的 10 + 5 會變成 105?
const rawScore = "10";
const bonus = 5;
console.log(rawScore + bonus); // "105"
+ 不只做數學加法,也能做 string concatenation。當 operand 包含 string 時,結果可能走字串語意。
不要先改 code。先看 evidence:
console.log(rawScore, typeof rawScore);
console.log(bonus, typeof bonus);
如果輸出:
10 string
5 number
現在你已經知道 bug 不在 CSS、不在 loop,而在資料 boundary:rawScore 仍是 string。
7. Explicit conversion:把外部資料轉成你真正要的型別
const rawScore = "10";
const score = Number(rawScore);
const total = score + 5;
console.log(total); // 15
console.log(typeof total); // "number"
常見 conversion:
| Code | Result | 注意 |
|---|---|---|
Number("42") | 42 | 成功轉 number |
Number(" 42 ") | 42 | 前後空白可被處理 |
Number("") | 0 | 常讓初學者意外 |
Number("abc") | NaN | 不是有效 numeric result |
String(42) | "42" | 常用於顯示/組字串 |
Boolean(0) | false | truthy/falsy 37 再深入 |
8. Worked Example C:NaN 是 failure evidence,不要把它當普通答案
const rawPrice = "NT$100";
const price = Number(rawPrice);
console.log(price); // NaN
console.log(Number.isNaN(price)); // true
NaN 仍然具有 JavaScript 的 number type,因此:
console.log(typeof NaN); // "number"
這也是為什麼單看 typeof 有時不夠。當你的 domain 需要「有效數值」,還要檢查 conversion result。
9. Common mistakes:這四種比背 API 更值得記
A. 把 input 看成 number
const qty = input.value; // 通常是 string
const total = qty + 1;
先查 typeof qty,再決定 conversion。
B. 用 const 後又做 reassignment
const score = 80;
score = 90;
如果 state 的確需要重新指定,用 let;如果不需要,就保留 const。
C. conversion failure 後繼續算
const value = Number("abc");
console.log(value + 10); // NaN
看到 NaN 應往資料 boundary 找,不是繼續堆更多 arithmetic。
D. 只看畫面,不看 runtime evidence
畫面顯示「105」只能說結果錯;console.log(value, typeof value) 才開始告訴你原因在哪。
10. Guided exercise:先預測,再跑
let value = "8";
value = Number(value);
value = value * 2;
value = String(value);
console.log(value, typeof value);
- 第一行後:value/value type?
- 第二行後:value/value type?
- 第三行後:value/value type?
- 最後輸出是
16 number還是16 string?
先寫 trace table,再在 Console 執行。不要直接跳到答案。
11. Independent exercise:做一個小型資料 boundary
寫一個 calculateSubtotal(rawPrice, rawQty):
- 兩個 arguments 都會是 string。
- 先明確轉成 number。
- 回傳 price × quantity。
- 至少測
"12.5","2"、"0","3"、"8","4"。
這題的重點不是乘法,是「外部資料進入 domain calculation 前先 normalize type」。
12. Challenge:找出 bug 在哪個 boundary
const priceInput = "20";
const qtyInput = "3";
const subtotal = priceInput * qtyInput;
const label = "Subtotal: " + subtotal;
console.log(label);
這段目前會得到看似正確的結果,但你仍然要回答:
- 為什麼
*在這裡似乎「自動成功」? - 你是否願意依賴這種 implicit conversion?
- 如果
priceInput變成"NT$20",failure evidence 會是什麼?
課程後續會逐步減少依賴隱式 coercion,讓資料 contract 更明確。
Project checkpoint:Grade Tracker 的第一個可靠 State
const studentName = "Anson";
const rawScore = "90";
const score = Number(rawScore);
console.log({
studentName,
score,
scoreType: typeof score
});
到這一課結束,你的專案還不需要 DOM、API 或漂亮 UI。真正的完成條件只有:資料進來後,你知道目前 value 是什麼、type 是什麼、哪個 binding 可以重新 assignment、哪個不可以。
13. Vocabulary / Summary
| Term | 精確抓法 |
|---|---|
| literal | 在 source code 中直接表示 value 的語法 |
| value | runtime 實際處理的資料 |
| identifier | 程式中的名稱 |
| binding | 名稱與目前 value 的關聯 |
| assignment | 把計算後的 value 指定給 binding |
| type | value 的資料種類,影響可用 operations |
| conversion | 明確把資料轉成另一種 type |
| NaN | 數值 operation/conversion 沒得到有效 numeric result 的特殊 number value |
14. Further reading
- MDN — Grammar and types
- MDN — JavaScript data types and data structures
- javascript.info — Variables
- javascript.info — Type Conversions
這些是延伸 reference;本站負責學習順序、mental model、可執行練習與 project progression,不直接複製外部教材文字。
Knowledge check:離開前你應該真的能做
- 看到
const x = "10",指出 literal、identifier、value、type。 - 逐行 trace
let x="5"; x=Number(x); x=x+1;。 - 解釋
const為什麼不是「所有資料都 immutable」。 - 說明
"5"+1與Number("5")+1為何不同。 - 看到
NaN時,提出至少兩個要檢查的 evidence。 - 完成頁面下方 Executable JS mastery lab,不只閱讀答案。