本文 AI 產出,尚未審核

JavaScript 數字(Number)


簡介

在 JavaScript 中,**數字(Number)**是最常使用的原始資料型別之一。幾乎所有的算術運算、索引、計時、統計分析,都離不開它。即使是看似簡單的「字串長度」或「陣列索引」,背後也會被自動轉型成數字來處理。

因此,對 Number 的特性與限制有清晰的認識,不只能寫出正確的程式碼,更能避免常見的 精度誤差隱式型別轉換 等陷阱,提升程式的可讀性與可維護性。本文針對初學者到中級開發者,系統說明 JavaScript 中的數字型別、常用方法與實務應用,並提供實作範例與最佳實踐建議。


核心概念

1. Number 的基本特性

  • JavaScript 只有一種數值型別 Number(除了 ES2020 之後的 BigInt),它採用 IEEE‑754 雙精度浮點數(64 位元)表示。
  • 整數小數在語法上沒有差別,皆屬於同一個型別。
let a = 42;        // 整數
let b = 3.14;      // 浮點數
console.log(typeof a, typeof b); // "number" "number"

2. 特殊值:NaN、Infinity、-Infinity

說明
NaN Not a Number,表示「不是一個有效的數字」;任何與 NaN 的算術運算結果仍為 NaN。
Infinity 正無限大,通常出現在除以 0 或超出可表示範圍的結果。
-Infinity 負無限大。
console.log(0 / 0);          // NaN
console.log(1 / 0);          // Infinity
console.log(-1 / 0);         // -Infinity

⚠️ 注意NaN === NaNfalse,必須使用 Number.isNaN() 判斷。

3. 數值常用屬性與方法

屬性 / 方法 說明
Number.MAX_VALUE 可表示的最大正數(約 1.79e+308)。
Number.MIN_VALUE 可表示的最小正數(約 5e-324),非負零。
Number.isNaN(value) 嚴格判斷是否為 NaN。
Number.isFinite(value) 判斷是否為有限數(非 NaN、非 Infinity)。
Number.parseInt(str, radix) 轉換字串為整數,第二參數 radix 為進位基數。
Number.parseFloat(str) 轉換字串為浮點數。
num.toString(radix) 以指定進位制(2~36)輸出字串。
num.toFixed(digits) 四捨五入保留小數位,回傳字串。
num.toPrecision(precision) 依有效位數返回字串。

程式碼範例

範例 1:使用 Number.isNaN 正確檢測 NaN

function safeDivide(a, b) {
  const result = a / b;        // 可能產生 NaN 或 Infinity
  if (Number.isNaN(result)) {
    return '除法結果不是有效數字';
  }
  if (!Number.isFinite(result)) {
    return '除法結果為無限大';
  }
  return result;
}

console.log(safeDivide(10, 0));   // "除法結果為無限大"
console.log(safeDivide(0, 0));    // "除法結果不是有效數字"
console.log(safeDivide(5, 2));    // 2.5

範例 2:避免字串轉數字時的隱式進位錯誤

// 錯誤寫法:直接使用 Number() 轉型,若字串開頭為 "0x" 會被當成十六進位
let hex = "0xFF";
console.log(Number(hex)); // 255 (意外的十六進位解讀)

// 正確寫法:明確指定十進位基數
let decimal = Number.parseInt(hex, 10);
console.log(decimal); // NaN,因為 "0xFF" 不是十進位數字

範例 3:浮點數精度問題與 toFixed 的使用

let sum = 0.1 + 0.2;      // 0.30000000000000004
console.log(sum);        // 0.30000000000000004

// 使用 toFixed 取兩位小數,結果為字串
let rounded = sum.toFixed(2);
console.log(rounded);    // "0.30"
console.log(Number(rounded) + 0.1); // 0.4,避免累積誤差

範例 4:parseInt 與基數的正確運用(常見陷阱)

let str1 = "08";          // 以 0 開頭的字串
console.log(Number.parseInt(str1));   // 8 (ES5 之後預設十進位)

let str2 = "1010";
console.log(Number.parseInt(str2, 2)); // 10,將二進位字串轉為十進位

範例 5:使用 BigInt 處理超大整數(ES2020)

// Number 無法正確表示超過 2^53-1 的整數
let large = 9007199254740993; // 超過安全範圍
console.log(large === large + 1); // true,失真

// 改用 BigInt
let big = 9007199254740993n; // 後綴 n 表示 BigInt
console.log(big === big + 1n); // false,正確比較

常見陷阱與最佳實踐

陷阱 說明 最佳實踐
浮點精度誤差 0.1 + 0.2 ≠ 0.3 使用 toFixed/toPrecision、或改用整數(如以「分」計算金額)
隱式型別轉換 == 會自動轉型,導致意外結果 永遠使用 ===,必要時手動 Number() 轉型
NaN 比較 NaN === NaNfalse 使用 Number.isNaN() 檢測
parseInt 省略基數 早期瀏覽器會把前導 0 當作八進位 永遠提供第二參數 radix
大數超出安全範圍 超過 Number.MAX_SAFE_INTEGER 會失真 使用 BigInt 或第三方大數庫
Infinity 與除以 0 1 / 0 產生 Infinity,可能導致邏輯錯誤 在計算前檢查除數是否為 0,或使用 Number.isFinite 之後再使用結果

實際應用場景

  1. 金額計算

    • 使用 整數(以「分」為單位)避免浮點誤差;最後顯示時再除以 100 並使用 toLocaleString 格式化。
  2. 分頁與索引

    • 透過 Number.isInteger(page) 確保使用者輸入的頁碼為正整數,防止非法索引。
  3. 隨機數產生

    • Math.random() 產生 [0,1) 的浮點數,配合 Math.floor 轉為整數區間。
    function randomInt(min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    
  4. 計時器與動畫

    • performance.now() 回傳毫秒的浮點數,可用於高精度時間測量;使用 requestAnimationFrame 時,時間參數自帶高精度。
  5. 科學計算

    • 需要控制有效位數時,使用 Number.toPrecision,例如顯示 3 個有效位數的結果。

總結

  • JavaScript 的 Number 只有一種,但涵蓋了整數、浮點數以及特殊值(NaN、Infinity)。
  • 了解 IEEE‑754 的限制,才能在實務開發中避免精度錯誤與隱式型別轉換帶來的 bug。
  • 使用 Number.isNaNNumber.isFiniteNumber.parseInt(帶基數) 等嚴格檢測與轉換方法,是寫出健全程式碼的關鍵。
  • 當需求超出安全整數範圍或需要極大數值時,BigInt 提供了可靠的解決方案。
  • 在日常開發(金額、分頁、隨機、計時、科學計算)中,依照最佳實踐處理數字,可提升程式的正確性與可維護性。

掌握了上述概念與技巧後,你就能在 JavaScript 中自信地使用數字,無論是簡單的加減或是複雜的金融計算,都能寫出正確、可靠且易於維護的程式碼。祝你在程式之路上,數字永遠為你服務,而不是成為阻礙!