Number.isNaN 回傳 false,輸入卻不是數字:表單驗證怎樣寫

表單輸入了「abc」,Number.isNaN() 卻回傳 false,接著計算總額才出現 NaN。問題在於它只檢查「這個值是不是 NaN」,不會先把字串轉成數字;false 並不表示輸入的是有效數字。

如果你正在修改數量欄位、運費試算或價格篩選,先分清兩件事:讀到的是字串還是數字,以及這個值是否符合欄位規則。下面以只接受非負整數的數量欄位為例,不涉及真實訂單或付款。

為什麼 abc 和空白都得到 false

Number.isNaN() 不做型別轉換。因此 NaN 會得到 true,但字串「abc」、空字串,甚至 undefined 都會得到 false。它適合檢查已經算出的數值,不適合單獨當作表單的「必須填數字」規則。

Number.isNaN(NaN);       // true
Number.isNaN("abc");     // false
Number.isNaN("");        // false
Number.isNaN(undefined); // false

const result = Number("abc");
Number.isNaN(result);    // true

全域的 isNaN() 會先轉成數字,所以 isNaN("abc") 是 true。但只換成這個函式,仍會漏掉空白:isNaN("") 和 isNaN(" ") 都是 false,因為這些字串轉換後是 0。

先擋空白,再轉換,再檢查範圍

以下函式接收字串;這正是一般文字輸入欄位 input.value 的形式。它先去掉頭尾空白,避免未填被轉成 0,再要求內容只含十進位數字,最後轉成 Number 並檢查有限值與安全整數範圍。回傳的 value 才交給後續計算。

function readQuantity(raw) {
  if (typeof raw !== "string") {
    return { ok: false, message: "輸入必須是字串" };
  }
  const text = raw.trim();
  if (text === "") {
    return { ok: false, message: "請填寫數量" };
  }
  if (!/^[0-9]+$/.test(text)) {
    return { ok: false, message: "請使用 0 到 9 的整數" };
  }
  const value = Number(text);
  if (!Number.isFinite(value) ||
      !Number.isSafeInteger(value)) {
    return { ok: false, message: "數量超出可處理範圍" };
  }
  return { ok: true, value };
}

readQuantity("0");   // { ok: true, value: 0 }
readQuantity("12");  // { ok: true, value: 12 }
readQuantity(" ");   // ok: false,未填
readQuantity("3件"); // ok: false,包含單位

這裡的 0 是允許值,不能用 if (!value) 判錯,否則 0 也會被擋掉。若你的購物車要求至少 1 件,應另加 value < 1 的判斷;有庫存或單次數量上限時,也要按實際規則檢查。安全整數範圍只處理 JavaScript 的數值表示限制,不代表允許購買那麼多。

有限數字也不一定是你要的輸入格式

Number.isFinite() 只在值本身是有限的 Number 時回傳 true;NaN、正負 Infinity 和字串都會得到 false。把「12」先轉成 12,才會得到 true。

Number.isFinite("12");         // false
Number.isFinite(Number("12")); // true
Number.isFinite(Infinity);     // false
Number.isFinite(NaN);          // false

不過,Number("1e3") 是 1000,Number("0x10") 是 16,兩者都是有限數字。若欄位只接受一般十進位整數,仍需像上例那樣先限制文字格式;不能只靠有限值檢查。全形數字「12」、帶逗號的「1,000」與小數「1.5」在本例都會被拒絕,畫面提示也應讓使用者知道接受哪種格式。

用這幾筆輸入核對自己的欄位

把函式貼進自己的測試頁或瀏覽器開發者工具,再依序輸入空字串、空格、0、12、3件、-1、1.5、1e3 和很長的一串 9。本例只有 0 與 12 會通過;「 12 」會先去除頭尾空格,仍得到 12。

如果計算結果仍是 NaN,往後找是否又拿原來的字串做運算,而沒有使用函式回傳的 value。前台檢查可以及早提示錯誤,但瀏覽器送出的資料仍可能被修改;正式儲存或計價時,伺服器也要依相同的格式、範圍和業務規則重新驗證。

參考資料

原文鏈接:https://wntheme.com/javascript-isnan-form-number-validation/,轉載請註明出處。
0
顯示驗證碼
沒有帳號?註冊  忘記密碼?