JavaScript 中的 `Number` 類別
本文將解釋 JavaScript 中的 Number 類別。
我們將一步步詳細說明 Number 的特性、常見陷阱、實用 API 以及實際範例。
YouTube Video
JavaScript 中的 Number 類別
Number 是 JavaScript 的基礎數值型別,採用 IEEE-754 雙精度浮點數(64 位元)表示。
基礎:數值表示與型別檢查
在 JavaScript 中,所有數字都以原始的 number 型別表示。
1// Primitive numbers and Number object
2const a = 42; // primitive number
3const b = 3.14; // primitive float
4const c = Number(10); // primitive via constructor call (function form)
5const d = new Number(10); // Number object (wrapper)
6
7console.log(typeof a); // "number"
8console.log(typeof d); // "object"
9console.log(c == d); // true (value coerces)
10console.log(c === d); // false (different types)
- 此程式碼展示了原始型別
number與Number包裝物件之間的差異。通常建議使用原始型別,而非包裝物件。
特殊值:NaN、Infinity 與常數
Number 提供了特殊值(NaN、Infinity)及常數。
1// Special numeric values and constants
2console.log(Number.NaN); // NaN
3console.log(Number.POSITIVE_INFINITY); // Infinity
4console.log(Number.NEGATIVE_INFINITY); // -Infinity
5
6console.log(Number.MAX_VALUE); // largest positive representable
7console.log(Number.MIN_VALUE); // smallest positive representable (closest to 0)
8console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
9console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
10console.log(Number.EPSILON); // smallest difference ~2.220446049250313e-16
- 大於或等於
MAX_SAFE_INTEGER的整數可能無法精確表示,若需要精確度請考慮使用BigInt。EPSILON用於浮點數比較。
數值轉換:Number()、parseInt、parseFloat 與 + 運算子
將字串轉換為數字有多種方法,每種方式行為略有不同。
1// Converting strings to numbers
2console.log(Number("42")); // 42
3console.log(Number(" 3.14 ")); // 3.14
4console.log(+ "7"); // 7 (unary +)
5
6console.log(parseInt("42px")); // 42
7console.log(parseFloat("3.14abc"));// 3.14
8
9// Careful with parseInt and radix
10console.log(parseInt("08")); // 8
11console.log(parseInt("08", 10)); // 8 (explicit radix is safer)
Number()除非整個字串為嚴格數值格式,否則會回傳NaN,而parseInt與parseFloat則會從字串開頭解析可讀的數字部分。使用parseInt時,建議務必明確指定基底(radix)。
處理與檢查 NaN:isNaN 與 Number.isNaN
NaN(Not-A-Number)很特別,因為 NaN !== NaN。兩者的判定方式不同;全域的 isNaN 會執行型別轉換,可能產生誤判,因此推薦使用 Number.isNaN。
1// NaN detection differences
2console.log(NaN === NaN); // false
3
4console.log(isNaN("foo")); // true -> because "foo" coerces to NaN
5console.log(Number.isNaN("foo")); // false -> "foo" is not the numeric NaN
6
7console.log(Number.isNaN(NaN)); // true
- 檢查數值與驗算結果時請用
Number.isNaN,以避免不必要的型別轉換。
浮點誤差及使用 Number.EPSILON 進行比較
因為 IEEE-754 規格會產生如 0.1 + 0.2 !== 0.3 這類誤差。嚴格比較時,通常會透過差值與 Number.EPSILON 來判斷。
1// Floating point precision example and EPSILON comparison
2const sum = 0.1 + 0.2;
3console.log(sum === 0.3); // false
4
5function nearlyEqual(a, b, epsilon = Number.EPSILON) {
6 return Math.abs(a - b) <= epsilon * Math.max(1, Math.abs(a), Math.abs(b));
7}
8
9console.log(nearlyEqual(sum, 0.3)); // true
- 若允許有誤差比較,建議實作如
nearlyEqual這類同時考慮比例與絕對差的健壯函式。
檢查整數與安全整數(isInteger、isSafeInteger)
有 API 可以檢查某值是否為整數,以及是否落於安全整數範圍內。
1// Integer and safe integer checks
2console.log(Number.isInteger(3)); // true
3console.log(Number.isInteger(3.0)); // true
4console.log(Number.isInteger(3.1)); // false
5
6console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
7console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
- 當需要大整數的精確性時,請使用
Number.isSafeInteger檢查,並針對超過範圍的數字考慮使用BigInt。
顯示與格式化:toFixed、toPrecision、toString
有方法可以控制數值的顯示格式。toFixed 會返回指定位數的小數字串,但要留意四捨五入的處理。
1// Formatting numbers for display
2const x = 1.23456;
3console.log(x.toFixed(2)); // "1.23" (string)
4console.log(x.toPrecision(3)); // "1.23" (string with total significant digits)
5console.log((255).toString(16)); // "ff" (hexadecimal string)
toFixed回傳的是字串,因此進行運算時要注意數值轉換後的結果。
關於字串連接與 + 運算子的注意事項
+ 運算子同時用於數字加法和字串連接,依據型別可能產生非預期結果。
1// Pitfall with + operator and type coercion
2console.log(1 + 2 + "px"); // "3px"
3console.log("px" + 1 + 2); // "px12"
4console.log(1 + "2" - 0); // 3 (string coerced to number for subtraction)
- 字串和數字混用時,建議明確使用
String()、Number()或樣板字面值來避免隱式型別轉換。
進階用法:Number.parseInt/Number.parseFloat、valueOf
Number.parseInt 與 Number.parseFloat 是全域函式的別名。valueOf 用來取得 Number 物件的原始值,但實務上很少需要。
1// Number.parseInt/parseFloat aliases and valueOf example
2console.log(Number.parseInt("100", 10)); // 100
3console.log(Number.parseFloat("3.14")); // 3.14
4
5const nObj = new Number(5);
6console.log(nObj.valueOf()); // 5
7console.log(nObj + 1); // 6 (object coerced to primitive)
- 使用
Number.parseInt與Number.parseFloat時要留意基底(radix)與輸入字串的修剪。通常應避免使用包裝物件。
參考:簡易工具範例-數值驗證函式
這裡提供集結常用檢查的小型實用函式。這能讓輸入驗證等作業變得更簡單。
1// Small number utility functions
2function toNumberStrict(value) {
3 // Return a Number or throw for invalid numeric strings
4 const n = Number(value);
5 if (typeof value === "string" && value.trim() === "") {
6 throw new Error("Empty string is not a valid number");
7 }
8 if (Number.isNaN(n)) {
9 throw new Error(`Invalid number: ${value}`);
10 }
11 return n;
12}
13
14function almostEqual(a, b, eps = Number.EPSILON) {
15 // Robust relative comparison
16 return Math.abs(a - b) <= eps * Math.max(1, Math.abs(a), Math.abs(b));
17}- 這些都是可重複用於輸入處理及比較的高通用性函式。拋出錯誤的實作對於驗證用途來說非常有用。
效能與最佳實踐總結
使用 Number 時,請留意以下實務重點。
- 基本上,請直接使用原始型別
number,避免使用new Number()。 - 字串轉數值時,視需求選擇
Number()(嚴格)或parseInt/parseFloat(部分擷取)。 - 請以
Number.isNaN和Number.isFinite進行安全判斷。 - 浮點數比較請用
Number.EPSILON或自行建立比較函式。 - 需要整數精確度時,請用
Number.isSafeInteger檢查,超出範圍時採用BigInt。 - 你可以使用
toFixed或toPrecision來進行顯示用的四捨五入,但請注意回傳值是字串。
總結
Number 是 JavaScript 中所有數字的基礎類型,包括整數、小數及特殊值(NaN 和 Infinity)。必須注意型別轉換與浮點誤差,並正確使用 Number.isNaN、Number.EPSILON 等方法。超過安全整數範圍時請用 BigInt,進行四捨五入與顯示時則使用 toFixed 或 toPrecision。
您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。