NaN & isNaN

NaN là cái thứ méo gì trong Js??

NaN (a.k.a Not a Number) là thuộc tính đại diện cho giá trị “không phải số”. Nghe có vẻ nhảm, nhưng thực sự nó để chỉ một giá trị không phải là số hợp lệ nói cách khác NaN là giá trị được trả về từ các phép toán có kết quả là số không xác định.

Sự thật tàn nhẫn về NaN

  • NaN là thứ duy nhất trong javascript không bằng chính nó. Vì IEEE (Institute of Electrical and Electronics Engineers – Hội Kỹ sư Điện và Điện tử) đã phán rằng các NaN không bằng nhau.
  • NaN là một phần của thông số kỹ thuật IEEE 754 biểu diễn số, vì vậy loại giá trị (typeof) của một NaN là số.
NaN === NaN    //false
typeof NaN     //number

Các hàm của Js để kiểm tra một giá trị là NaN

  • isNaN()

Bản chất của hàm isNaN() là như thế này:

const isNaN = function(value) {
    const n = Number(value);
    return n !== n;
};

Nhìn đoạn code ở trên là các bác cũng hiểu rồi đúng không, trước khi isNaN() làm nhiệm vụ kiểm tra có phải là NaN hay không thì đã tự động chuyển đổi type của tham số truyền vào (như string/number…) sang type là number bằng hàm Number() – các bác nhớ kỹ giúp tôi là Number() chứ không phải là parseInt() nha.

isNaN(NaN);       // true
isNaN(undefined); // true
isNaN({});        // true

isNaN(true);      // false (vì convert true thành 1)
isNaN(null);      // false (vì convert null thành 0)
isNaN(37);        // false

isNaN('37');      // false (vì convert "37" thành 37)
isNaN('37.5');   // false (vì "37.5" thành 37.5)
isNaN('');        // false (vì chuỗi rỗng được convert thành 0)
isNaN('1A');  // true (vì Number("1A") là NaN, nhưng nếu dùng parseInt("1A") thì kết quả là 1)
  • Number.isNaN()

Như các bác cũng thấy ở phần trên bản thân hàm isNaN() có một sự nguy hiểm không hề nhẹ vì nó đã tự động biến đổi bản chất của tham số truyền vào sang dạng khác, do vậy tôi khuyên các bác nên sử dụng Number.isNaN() (mới được giới thiệu trong ES6) thay vì người chị của nó.

Bản chất của hàm Number.isNaN() là như thế này

Number.isNaN = Number.isNaN || function isNaN(input) {
    return typeof input === 'number' && input !== input;
}
Number.isNaN(NaN);        // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0);      // true

Number.isNaN('NaN');      // false
Number.isNaN(undefined);  // false
Number.isNaN({});         // false
Number.isNaN('blabla');   // false

Number.isNaN(true); // false
Number.isNaN(null); // false
Number.isNaN(37); // false
Number.isNaN('37'); // false
Number.isNaN('37.37'); // false
Number.isNaN(''); // false
Number.isNaN(' '); // false

Bài viết được viết bởi: https://github.com/maxiromanoff