Lớp `Number` trong JavaScript
Bài viết này giải thích về lớp Number trong JavaScript.
Chúng tôi sẽ giải thích cẩn thận các đặc điểm của Number, các lỗi phổ biến, API hữu ích và ví dụ thực tiễn từng bước một.
YouTube Video
Lớp Number trong JavaScript
Number là kiểu số cơ bản trong JavaScript và được biểu diễn theo chuẩn số thực dấu phẩy động hai lần chính xác IEEE-754 (64 bit).
Cơ bản: Biểu diễn số và kiểm tra kiểu dữ liệu
Trong JavaScript, tất cả các số đều được biểu diễn dưới dạng kiểu nguyên thủy 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)
- Đoạn mã này minh họa sự khác biệt giữa kiểu nguyên thủy
numbervà đối tượng bao bọcNumber. Thông thường, kiểu nguyên thủy được sử dụng thay cho đối tượng bao.
Giá trị đặc biệt: NaN, Infinity và các hằng số
Number cung cấp các giá trị đặc biệt (NaN, Infinity) và các hằng số.
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
- Các số nguyên lớn hơn hoặc bằng
MAX_SAFE_INTEGERcó thể không được biểu diễn chính xác. Hãy cân nhắc sử dụngBigIntnếu cần độ chính xác cao.EPSILONđược sử dụng cho so sánh số thực dấu phẩy động.
Chuyển đổi số: Number(), parseInt, parseFloat và toán tử +
Có nhiều cách để chuyển đổi chuỗi sang số, mỗi cách có hành vi khác nhau.
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()trả vềNaNtrừ khi toàn bộ chuỗi hoàn toàn là số, cònparseIntvàparseFloatsẽ lấy phần có thể chuyển đổi thành số từ đầu chuỗi. Nên chỉ định rõ ràng cơ số khi sử dụngparseIntđể đảm bảo an toàn.
Xử lý và kiểm tra NaN: isNaN và Number.isNaN
NaN (Not-A-Number) là giá trị đặc biệt vì NaN !== NaN. Có sự khác biệt về cách kiểm tra; hàm toàn cục isNaN thực hiện chuyển đổi kiểu và có thể cho kết quả sai, do đó nên sử dụng 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
- Sử dụng
Number.isNaNđể kiểm tra số và xác thực kết quả tính toán để tránh chuyển đổi kiểu không cần thiết.
Lỗi số thực dấu phẩy động và so sánh sử dụng Number.EPSILON
Do chuẩn IEEE-754, có thể xảy ra lỗi như 0.1 + 0.2 !== 0.3. Khi cần so sánh chặt chẽ, thường sử dụng hiệu số và 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
- Khi cho phép lỗi nhỏ trong phép so sánh, nên sử dụng triển khai mạnh như
nearlyEqual, vừa dùng phép so sánh theo tỷ lệ vừa dùng độ lệch tuyệt đối.
Kiểm tra số nguyên và số nguyên an toàn (isInteger, isSafeInteger)
Có các API để kiểm tra xem một giá trị có phải là số nguyên và nằm trong phạm vi số nguyên an toàn không.
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
- Khi cần độ chính xác với số nguyên lớn, hãy sử dụng
Number.isSafeIntegerđể kiểm tra, và cân nhắc sử dụngBigIntnếu vượt quá phạm vi đó.
Hiển thị và định dạng: toFixed, toPrecision, toString
Có những phương thức để kiểm soát cách hiển thị số. toFixed trả về chuỗi với số chữ số thập phân xác định, nhưng cần chú ý đến việc làm tròn số.
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)
toFixedtrả về một chuỗi, nên cần chú ý sau khi chuyển đổi sang số để thực hiện phép tính.
Lưu ý khi nối chuỗi và sử dụng toán tử +
Toán tử + dùng để cộng số và nối chuỗi, nên có thể xảy ra kết quả không mong muốn tuỳ thuộc kiểu dữ liệu đầu vào.
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)
- Khi trộn lẫn chuỗi và số, hãy sử dụng rõ ràng
String(),Number()hoặc template literals để tránh chuyển đổi kiểu ngầm.
Trường hợp sử dụng nâng cao: Number.parseInt / Number.parseFloat, valueOf
Number.parseInt và Number.parseFloat là các bí danh của những hàm toàn cục. valueOf được dùng để lấy giá trị nguyên thủy từ đối tượng Number, nhưng thực tế rất ít khi cần sử dụng.
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)
- Khi sử dụng
Number.parseIntvàNumber.parseFloat, hãy chú ý đến cơ số và việc loại bỏ khoảng trắng ở đầu/cuối. Thông thường nên tránh sử dụng đối tượng bao.
Tham khảo: Ví dụ tiện ích nhỏ - Các hàm kiểm tra số
Dưới đây là một số hàm tiện ích nhỏ thu thập các kiểm tra thường dùng. Điều này giúp kiểm tra tính hợp lệ của dữ liệu đầu vào dễ dàng hơn.
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}- Chúng là những hàm đa năng có thể sử dụng nhiều lần cho việc xử lý đầu vào và so sánh. Các hàm ném lỗi rất hữu ích cho mục đích kiểm tra tính hợp lệ.
Tóm tắt về hiệu suất và các thực tiễn tốt nhất
Dưới đây là những điểm thực tế khi sử dụng Number.
- Về cơ bản, hãy sử dụng kiểu số nguyên thủy
numbervà tránh dùngnew Number(). - Tùy từng trường hợp mà chọn sử dụng
Number()(nghiêm ngặt) hoặcparseInt/parseFloat(lấy một phần) để chuyển đổi chuỗi sang số. - Sử dụng
Number.isNaNvàNumber.isFiniteđể kiểm tra an toàn. - Đối với so sánh số thực dấu phẩy động, hãy sử dụng
Number.EPSILONhoặc tạo một hàm so sánh chuyên dụng. - Khi cần độ chính xác với số nguyên, hãy dùng
Number.isSafeInteger, và nếu vượt quá phạm vi cho phép, hãy sử dụngBigInt. - Bạn có thể sử dụng
toFixedhoặctoPrecisionđể làm tròn khi hiển thị, nhưng lưu ý rằng giá trị trả về là một chuỗi.
Tóm tắt
Number là kiểu cơ bản cho tất cả các số trong JavaScript, bao gồm số nguyên, số thập phân và các giá trị đặc biệt (NaN và Infinity). Cần chú ý đến chuyển đổi kiểu dữ liệu và lỗi số thực dấu phẩy động, đồng thời sử dụng đúng các phương thức như Number.isNaN và Number.EPSILON. Nếu vượt quá phạm vi số nguyên an toàn, hãy sử dụng BigInt và dùng toFixed hoặc toPrecision để làm tròn và hiển thị.
Bạn có thể làm theo bài viết trên bằng cách sử dụng Visual Studio Code trên kênh YouTube của chúng tôi. Vui lòng ghé thăm kênh YouTube.