商品數量欄位收到「12px」,程式卻照樣當成12送出?如果你用parseInt(value, 10)判斷輸入是否合法,就可能遇到這個問題。它能讀取開頭的整數部分,並不要求整個字串都是數字。
先看被截掉的是哪一段
在瀏覽器Console貼上這幾行,留意字串尾巴以及小數點之後的內容。
console.log(parseInt('12px', 10)) // 12
console.log(parseInt('12.8', 10)) // 12
console.log(parseInt('1e3', 10)) // 1
console.log(parseInt('px12', 10)) // NaN
前三個例子都能從開頭讀到數字,遇到不能當作十進位數字的字元便停止。最後一個連開頭都讀不到數字,才得到NaN。所以「結果不是NaN」只代表讀到某個整數部分,不能證明輸入符合數量欄位的要求。
先定義數量欄位接受什麼
假設購物表單接受1至99件、只允許十進位數字,不接受正負號、小數、指數或單位;前後空白可忽略,前導零也可接受。這是下面案例的規則,99不是所有網站都適用的上限。
function readQuantity(raw) {
if (typeof raw !== 'string') return null
const text = raw.trim()
if (!/^[0-9]+$/.test(text)) return null
const quantity = Number(text)
if (!Number.isSafeInteger(quantity)) return null
if (quantity < 1 || quantity > 99) return null
return quantity
}
先確認整個去除前後空白後的字串都由數字組成,再轉成Number,最後核對安全整數與範圍。空字串過不了第一道格式檢查,「12px」也不能只靠開頭的12過關。null表示拒絕輸入,別把它再轉成0送出。
這個函式要接收輸入框的字串value。如果你改用已轉成數字的資料,或要接受小數與正負號,就應重新定義規則,不能直接照搬這個格式檢查。
用幾個容易漏掉的值試一次
先貼上完整函式,再貼下面的呼叫。函式名稱相同時不要在同一測試檔重複宣告多份。
for (const raw of [
'12', ' 12 ', '012', '12px', '12.8',
'1e3', '', ' ', '0', '100', '+12'
]) {
console.log(JSON.stringify(raw), readQuantity(raw))
}
依這組規則,前三項回傳12,其餘回傳null。若你不允許「012」這類前導零,也要把它寫進格式規則與測試,而不是期待轉成數字後仍保留原樣。
換成Number也不能省掉格式規則
Number('12px')會得到NaN,但它接受的格式不只一般十進位數字字串,空字串也有特別的轉換結果。
console.log(Number('')) // 0
console.log(Number(' ')) // 0
console.log(Number('1e3')) // 1000
console.log(Number('0x10')) // 16
如果欄位只接受一般數量,把parseInt換成Number再檢查範圍,仍可能讓不想接受的格式通過。先查完整字串,再轉換,才能把「轉換得出數字」與「符合表單規格」分清。
前端提示之外,伺服器還要再驗證
前端檢查適合即時提醒使用者修改輸入;伺服器收到請求後仍要按照同一業務規則核對數量、範圍及可購庫存。使用者可以繞過頁面直接送請求,不能把前端函式當作訂單成立的唯一依據。
商品編號、電話或帶前導零的識別碼,也不一定適合轉成數字。先問這個欄位是否真的要做算術:若只是識別或顯示,保留字串往往更合適。超出安全整數範圍的資料也不能靠parseInt保證精度。

評論0