今天正式碰到 QA 熟悉的東西——條件判斷。基本語法是這樣:
let hp = 50;
if (hp <= 0) {
console.log("勇者陣亡");
} else if (hp < 30) {
console.log("勇者身受重傷");
} else {
console.log("勇者狀態正常");
}
邏輯是由上往下依序檢查,只要有一個條件成立就執行對應區塊,後面就不再檢查。
=== 還是 ==?我先猜錯了一次JavaScript 有兩種「等於」:== 和 ===。在動手測之前,我先猜了一下 0 == false 和 0 === false 這兩個算式的結果,我猜兩個都是 false——畢竟 0 是數字、false 是布林,型別不一樣,感覺怎麼比都不該相等。
實際跑了才發現我猜錯一半:
console.log(0 == false); // true
console.log(0 === false); // false

0 == false 居然是 true,0 === false 才是我原本以為的 false。查了才搞懂:== 在比較之前,會先偷偷把兩邊的型別轉成同一種再比(false 被轉成數字 0 之後,兩邊就相等了),而 === 不會做這個轉換,型別不一樣就直接判定不相等。
用 QA 的角度看,== 這種「偷偷幫你轉型別再比」的行為,很容易讓型別不對的問題被矇混過關;=== 的嚴格比對更接近測試斷言該有的態度——不相等就是不相等,不會因為背後偷做轉換而放水。這次的練習我全程只用 ===。
我寫了一個判斷 HP 狀態的函式:
function checkStatus(hp) {
if (hp <= 0) {
console.log(hp, "→ 勇者陣亡");
} else if (hp < 30) {
console.log(hp, "→ 身受重傷");
} else {
console.log(hp, "→ 狀態正常");
}
}
//帶入不同數值看看會出什麼結果
checkStatus(100);
checkStatus(20);
checkStatus(0);
checkStatus(-10);
四個測試案例的結果都符合預期:
100 → 狀態正常
20 → 身受重傷
0 → 勇者陣亡
-10 → 勇者陣亡

但我沒有就此停手,而是想到還有一個邊界沒測到:HP 剛好等於 30 會怎樣?
跑了 checkStatus(30),結果是「狀態正常」——因為條件是 hp < 30(嚴格小於),30 < 30 是 false,所以直接跳到 else。

這裡我停下來想了一下:這個結果符合原本的意圖嗎? 我認為是符合的——既然條件寫的是「小於 30 才算重傷」,那「大於等於 30」理所當然都算未陣亡的正常狀態,30 本來就該落在「正常」這一邊,不是漏洞。
但我還是決定在程式碼裡補一行註解,標明這個邊界的判斷方式,原因是:「30 剛好落在哪一邊」這種問題,如果沒有寫下來,幾個月後回頭看程式碼、或是別人接手時,很容易搞不清楚這是刻意設計還是不小心漏掉。與其讓人猜,不如當下就寫清楚:
} else {
console.log(hp, "→ 狀態正常"); // 註:30 本身不算重傷,30 以上都算正常
}
這是我在 QA 工作裡學到的習慣:邊界值不只要測,測完之後的判斷理由,也值得留下紀錄,不然「這是故意的」和「這是漏洞」看起來會一模一樣。
checkStatus 是什麼意思?寫這段程式碼時,我一度把 function 這個關鍵字跟 Python 的 input()搞混,後來查證後確認:
function(JS)對應的其實是 Python 的 def,兩者都是「定義一個可重複呼叫的函式」input()(跟使用者要輸入值)的,是 JS 的 prompt(),這次練習完全沒用到另外 checkStatus 本身不是 JavaScript 的關鍵字,是我自己取的名字,單純因為這個函式的功能是「檢查狀態」,取這個名字方便理解,換成別的名字功能也一樣。JS 圈子習慣用「駝峰式命名」(第一個字小寫,後面每個新單字開頭大寫),像 checkStatus、heroName 都是這樣寫。
今天搞懂的事:
0 == false 是 true、0 === false 才是 false,跟我原本的直覺相反,因為 == 會偷偷做型別轉換再比較——之後一律用 ===
function 對應 Python 的 def,不是 input();函式名稱是自己取的,不是關鍵字明天繼續學陣列——一群資料的容器。