NaN
Baseline
Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Thuộc tính toàn cục NaN là một giá trị đại diện cho Not-A-Number (Không phải số).
Try it
function sanitize(x) {
if (isNaN(x)) {
return NaN;
}
return x;
}
console.log(sanitize("1"));
// Expected output: "1"
console.log(sanitize("NotANumber"));
// Expected output: NaN
Giá trị
Cùng giá trị số với Number.NaN.
Property attributes of NaN | |
|---|---|
| Writable | no |
| Enumerable | no |
| Configurable | no |
Mô tả
NaN là một thuộc tính của đối tượng toàn cục. Nói cách khác, nó là một biến trong phạm vi toàn cục.
Trong các trình duyệt hiện đại, NaN là một thuộc tính không thể cấu hình và không thể ghi. Ngay cả khi điều này không phải là trường hợp, hãy tránh ghi đè lên nó.
Có năm loại thao tác khác nhau trả về NaN:
- Chuyển đổi số thất bại (ví dụ: chuyển đổi tường minh như
parseInt("blabla"),Number(undefined), hoặc chuyển đổi ngầm nhưMath.abs(undefined)) - Thao tác toán học mà kết quả không phải là số thực (ví dụ:
Math.sqrt(-1)) - Dạng bất định (ví dụ:
0 * Infinity,1 ** Infinity,Infinity / Infinity,Infinity - Infinity) - Một phương thức hoặc biểu thức mà toán hạng của nó là hoặc bị ép kiểu thành
NaN(ví dụ:7 ** NaN,7 * "blabla") — điều này có nghĩa làNaNcó tính lây lan - Các trường hợp khác khi một giá trị không hợp lệ được biểu diễn dưới dạng số (ví dụ: một Date không hợp lệ
new Date("blabla").getTime(),"".charCodeAt(1))
NaN và các hành vi của nó không phải do JavaScript phát minh ra. Ngữ nghĩa của nó trong số học dấu phẩy động (bao gồm cả NaN !== NaN) được quy định bởi IEEE 754. Các hành vi của NaN bao gồm:
- Nếu
NaNtham gia vào một thao tác toán học (nhưng không phải toán tử bitwise), kết quả thường cũng làNaN. (Xem ví dụ phản chứng bên dưới.) - Khi
NaNlà một trong các toán hạng của bất kỳ so sánh quan hệ nào (>,<,>=,<=), kết quả luôn làfalse. NaNđược so sánh là không bằng (thông qua==,!=,===, và!==) với bất kỳ giá trị nào khác — kể cả một giá trịNaNkhác.
NaN cũng là một trong các giá trị falsy trong JavaScript.
Ví dụ
>Kiểm tra với NaN
Để xác định xem một giá trị có phải là NaN không, hãy dùng Number.isNaN() hoặc isNaN() để xác định rõ ràng nhất liệu một giá trị có phải là NaN không — hoặc, vì NaN là giá trị duy nhất được so sánh là không bằng chính nó, bạn có thể thực hiện so sánh với chính nó như x !== x.
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true
Number.isNaN(NaN); // true
function valueIsNaN(v) {
return v !== v;
}
valueIsNaN(1); // false
valueIsNaN(NaN); // true
valueIsNaN(Number.NaN); // true
Tuy nhiên, hãy lưu ý sự khác biệt giữa isNaN() và Number.isNaN(): hàm trước sẽ trả về true nếu giá trị hiện tại là NaN, hoặc nếu nó sẽ trở thành NaN sau khi bị ép kiểu thành số, trong khi hàm sau chỉ trả về true nếu giá trị hiện tại là NaN:
isNaN("hello world"); // true
Number.isNaN("hello world"); // false
Vì lý do tương tự, sử dụng giá trị BigInt sẽ ném ra lỗi với isNaN() nhưng không ném với Number.isNaN():
isNaN(1n); // TypeError: Conversion from 'BigInt' to 'number' is not allowed.
Number.isNaN(1n); // false
Ngoài ra, một số phương thức mảng không thể tìm thấy NaN, trong khi một số khác có thể. Cụ thể, các phương thức tìm kiếm theo chỉ mục (indexOf(), lastIndexOf()) không thể tìm thấy NaN, trong khi các phương thức tìm kiếm theo giá trị (includes()) có thể:
const arr = [2, 4, NaN, 12];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true
// Methods accepting a properly defined predicate can always find NaN
arr.findIndex((n) => Number.isNaN(n)); // 2
Để biết thêm thông tin về NaN và cách so sánh của nó, xem So sánh bằng và đồng nhất.
Các giá trị NaN có thể phân biệt được
Có thể tạo ra hai số dấu phẩy động với các biểu diễn nhị phân khác nhau nhưng cả hai đều là NaN, vì trong mã hóa IEEE 754, bất kỳ số dấu phẩy động nào có số mũ 0x7ff và phần định trị khác không đều là NaN. Trong JavaScript, bạn có thể thực hiện thao tác ở cấp bit bằng cách sử dụng typed arrays.
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);
const b2f = (x) => new Float64Array(x.buffer)[0];
// Get a byte representation of NaN
const n = f2b(NaN);
const m = f2b(NaN);
// Change the sign bit, which doesn't matter for NaN
n[7] += 2 ** 7;
// n[0] += 2**7; for big endian processors
const nan2 = b2f(n);
console.log(nan2); // NaN
console.log(Object.is(nan2, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan2)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 255]
// Change the first bit, which is the least significant bit of the mantissa and doesn't matter for NaN
m[0] = 1;
// m[7] = 1; for big endian processors
const nan3 = b2f(m);
console.log(nan3); // NaN
console.log(Object.is(nan3, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan3)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127]
Thoát khỏi NaN một cách im lặng
NaN lan truyền qua các thao tác toán học, vì vậy thông thường chỉ cần kiểm tra NaN một lần ở cuối phép tính để phát hiện các điều kiện lỗi. Trường hợp duy nhất mà NaN thoát khỏi một cách im lặng là khi sử dụng lũy thừa với số mũ là 0, lập tức trả về 1 mà không kiểm tra giá trị của cơ số.
NaN ** 0 === 1; // true
Thông số kỹ thuật
| Specification |
|---|
| ECMAScript® 2027 Language Specification> # sec-value-properties-of-the-global-object-nan> |