本文 AI 產出,尚未審核
JavaScript 數學與數字處理 – Number 物件方法(isNaN、isFinite、parseInt…)
簡介
在 JavaScript 中,數字是程式邏輯、使用者輸入驗證、資料庫查詢、圖形繪製等各種情境的基礎。雖然 Number 看似簡單,但它的行為卻常常讓新手感到困惑:NaN 與 Infinity 的判斷、字串轉成數字的細節、以及不同環境下全域函式與 Number 靜態方法的差異,都可能成為 bug 的根源。
本篇文章聚焦在 Number 物件常用的幾個方法:Number.isNaN、Number.isFinite、Number.isInteger、parseInt、parseFloat,以及與之相關的 toFixed、toPrecision。透過深入說明與實務範例,幫助你在日常開發中正確、有效率地處理數字與型別轉換。
核心概念
1. Number.isNaN vs 全域 isNaN
| 方法 | 目的 | 會自動型別轉換? |
|---|---|---|
Number.isNaN(value) |
僅在 value 本身是 NaN 時回傳 true |
否 |
isNaN(value)(全域) |
先把 value 轉成數字,若結果是 NaN,則回傳 true |
是 |
為什麼要區分?
isNaN的隱式型別轉換會把非數字字串、布林值等誤判為NaN,在資料驗證時容易產生錯誤。
// 全域 isNaN 會先轉型
console.log(isNaN('123')); // false → 先變成 123,再判斷不是 NaN
console.log(isNaN('foo')); // true → 轉成 NaN
console.log(isNaN(true)); // false → true → 1
// Number.isNaN 只檢查原始值是否為 NaN
console.log(Number.isNaN('123')); // false
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN('foo')); // false,因為字串本身不是 NaN
最佳實踐:在需要嚴格判斷「是否真的為 NaN」時,使用 Number.isNaN;若你想判斷「是否能被轉成有效數字」則可使用 Number.isFinite(見下)。
2. Number.isFinite vs 全域 isFinite
| 方法 | 目的 | 會自動型別轉換? |
|---|---|---|
Number.isFinite(value) |
僅在 value 為有限數字(非 NaN、非 Infinity、非 -Infinity)時回傳 true |
否 |
isFinite(value)(全域) |
先把 value 轉成數字,若結果是有限數字,則回傳 true |
是 |
// 全域 isFinite 會把字串轉成數字
console.log(isFinite('10')); // true
console.log(isFinite('abc')); // false → 轉成 NaN
// Number.isFinite 必須是已經是數字型別
console.log(Number.isFinite(10)); // true
console.log(Number.isFinite('10')); // false
console.log(Number.isFinite(Infinity)); // false
使用情境:
- 表單驗證:確保使用者輸入的是「真實的有限數字」時,建議先
Number(value)再使用Number.isFinite。 - 計算安全性:在做除法或指數運算前,先檢查分母或底數是否為有限,避免
Infinity或NaN造成後續錯誤。
3. parseInt、parseFloat 與 Number 建構子
| 方法 | 作用 | 會忽略什麼 | 進位基數 |
|---|---|---|---|
parseInt(string, radix) |
從字串最左側開始解析,直到遇到非數字字符為止,回傳 整數 | 前導空白、非數字字元 | 可指定 2~36(預設 10,若字串以 0x 開頭則自動為 16) |
parseFloat(string) |
同上,但允許小數點與指數符號,回傳 浮點數 | 前導空白、非數字字元 | 只支援十進位 |
Number(string) |
完全把字串轉成數字,若字串不是合法數字則回傳 NaN |
前導/尾端空白會被忽略,整體必須是合法的數字表示 | 只支援十進位(含科學記號) |
// parseInt 只會解析到第一個非數字字符
console.log(parseInt('42px')); // 42
console.log(parseInt('0xFF')); // 255 (十六進位)
console.log(parseInt('101', 2)); // 5 (二進位)
// parseFloat 允許小數點與指數
console.log(parseFloat('3.14abc')); // 3.14
console.log(parseFloat('2e3')); // 2000
// Number 需要整體符合數字格式
console.log(Number('123')); // 123
console.log(Number('123abc')); // NaN
console.log(Number(' 7 ')); // 7 (前後空白會被剔除)
小技巧:
- 若你只需要「把字串轉成完整的數字」且不想容忍後面的雜訊,使用
Number或+(一元正號)是最安全的。 parseInt常在 CSS 計算、字串前綴(如data-id="123-item")中使用,但要注意基數的正確設定,避免意外的十六進位解析。
4. Number.isInteger
判斷一個值是否為 整數(不含小數點、指數等),且必須是 Number 類型。
console.log(Number.isInteger(10)); // true
console.log(Number.isInteger(10.0)); // true (10.0 仍被視為整數)
console.log(Number.isInteger(10.5)); // false
console.log(Number.isInteger('10')); // false (字串不算)
此方法在 分頁、陣列索引、頁碼驗證 等需要整數的情境特別有用。
5. Number.prototype.toFixed、toPrecision
| 方法 | 目的 | 回傳值型別 |
|---|---|---|
num.toFixed(digits) |
四捨五入至指定的小數位數,回傳 字串 | string |
num.toPrecision(precision) |
依總位數(包含整數部)四捨五入,回傳 字串 | string |
let price = 12.34567;
// 只保留兩位小數
console.log(price.toFixed(2)); // "12.35"
// 以 4 位有效數字呈現
console.log(price.toPrecision(4)); // "12.35"
注意:
toFixed會自動補零(例如1.5.toFixed(3) → "1.500"),適合顯示金額或統計數值。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方式 |
|---|---|---|
NaN === NaN 為 false |
NaN 與任何值(包括自己)比較都不相等。 |
使用 Number.isNaN(value) 來檢測。 |
全域 isNaN 產生誤判 |
會把 ' '、true、null 轉成 0,導致 false 結果。 |
改用 Number.isNaN 或 Number.isFinite。 |
parseInt('08') 在舊版瀏覽器被視為八進位 |
早期 ECMAScript 會把以 0 開頭的字串當作八進位。 |
明確指定基數:parseInt('08', 10)。 |
| 浮點數精度問題 | 0.1 + 0.2 !== 0.3 因二進位表示誤差。 |
使用 toFixed、Math.round 或第三方精確數學函式庫(如 Decimal.js)。 |
Number('') 會得到 0 |
空字串被視為 0,可能不是預期行為。 | 先檢查字串長度或使用 trim() 再轉型。 |
toFixed 產生字串 |
若直接用於算術運算會自動轉成數字,但可能產生隱式型別轉換。 | 需要時使用 Number(num.toFixed(2))。 |
最佳實踐總結
- 驗證數值時:先使用
Number(value)轉型,接著Number.isFinite+Number.isNaN進行嚴格檢查。 - 解析字串時:若只要前綴數字,用
parseInt/parseFloat,但一定要指定基數;若需要完整、嚴格的轉換,用Number。 - 顯示結果:使用
toFixed或toPrecision,記得結果是字串,必要時再轉回Number。 - 避免隱式型別轉換:盡量不依賴全域
isNaN、isFinite,改用Number靜態方法。
實際應用場景
1. 表單金額驗證
function validateAmount(input) {
const raw = input.trim(); // 去除前後空白
const amount = Number(raw); // 完全轉成數字
if (!Number.isFinite(amount)) {
return '金額必須是有效的數字';
}
if (amount < 0) {
return '金額不可為負數';
}
// 四捨五入到小數點第二位,避免浮點誤差
const fixed = Number(amount.toFixed(2));
return fixed;
}
// 範例
console.log(validateAmount(' 123.456 ')); // 123.46
console.log(validateAmount('abc')); // '金額必須是有效的數字'
2. 分頁索引檢查
function getPage(data, pageStr, pageSize = 10) {
const page = Number(pageStr);
if (!Number.isInteger(page) || page < 1) {
throw new Error('頁碼必須為正整數');
}
const start = (page - 1) * pageSize;
return data.slice(start, start + pageSize);
}
3. 解析 CSS 計算式
function extractPixelValue(cssValue) {
// 只取前面的數字部分,忽略單位
const num = parseInt(cssValue, 10);
if (Number.isNaN(num)) {
throw new Error('不是有效的 pixel 值');
}
return num; // 回傳純數字
}
console.log(extractPixelValue('250px')); // 250
4. 科學計算與指數顯示
function formatScientific(num, sig = 4) {
if (!Number.isFinite(num)) return String(num);
return Number(num.toPrecision(sig));
}
console.log(formatScientific(0.000123456)); // 0.0001235
console.log(formatScientific(123456789, 3)); // 1.23e+8
總結
Number.isNaN、Number.isFinite、Number.isInteger為 嚴格檢查 方法,避免全域函式的隱式型別轉換。parseInt、parseFloat適合 從字串前綴擷取數字,但必須留意基數與字串結構。Number()(或+value)是 完整且安全 的字串→數字轉換,配合Number.isFinite可實作堅固的驗證邏輯。toFixed、toPrecision用於 顯示,記得它們回傳字串,必要時再轉回Number。- 熟悉這些方法的差異與限制,能讓你在 表單驗證、資料處理、UI 顯示、科學計算 等各種場景中寫出更可靠、可維護的程式碼。
掌握好這些基礎工具,你就能在 JavaScript 的數字世界裡游刃有餘,避免常見的陷阱,寫出更健全的程式!祝開發順利 🚀