Number.isNaN và isNaN hiểu về sự khác biệt trong javascript

Nội dung bài viết

Video học lập trình mỗi ngày

isNaN()Number.isNaN() trong javascript gây nhiều nhầm lẫn cho các devjs mới thậm chí là những devjs có nhiều kinh nghiệm. Nếu bạn trả lời câu hỏi này một các rành mạch thì không cần đọc bài viết này nữa, ngược lại thì bạn nên dành thời gian tìm hiểu isNaN trong javascript là gì? Và xin nhớ đây là một trong những bài viết Series - Mẹo viết javascript.


Number.isNaN và isNaN khác nhau như thế nào?


Trước tiên hãy xem ví dụ sau:

 console.log(isNaN(NaN))

console.log(isNaN('Anonystick.com'))

console.log(isNaN(undefined))

console.log(isNaN({}))

console.log(Number.isNaN(NaN))

console.log(Number.isNaN('Anonystick.com'))

console.log(Number.isNaN(undefined))

console.log(Number.isNaN({}))


Dừng lại tầm 1 phút, để cho bạn nhìn, suy nghĩ và trả lời. Cố thử xem mình trả lời đúng được mấy câu? Nếu đúng hết, bạn có thể leave, còn không hãy theo dõi tại sao mình lại sai. Câu trả lời như sau:


console.log(isNaN(NaN)) //true

console.log(isNaN('Anonystick.com')) //true

console.log(isNaN(undefined)) //true

console.log(isNaN({})) //true

console.log(Number.isNaN(NaN)) //true
console.log(Number.isNaN('Anonystick.com')) //false

console.log(Number.isNaN(undefined)) //false

console.log(Number.isNaN({})) //false

Tại sao cùng một hàm trông giống nhau, nhưng tại sao kết quả lại khác nhau? Từ từ phân tích


NaN là gì?


Trước khi giải thích về NaN, thì điều kiện tiên quyết là phải hiểu về 7 kiểu dữ liệu trong javascript. Qua bài viết trước thì chúng ta biết được Trong JavaScript, có 7 loại giá trị, và cần hiểu thêm một khái niệm nữa đó là var (biến). Xem phần đầu tiên của bài viết về kiểu dữ liệu


Thuộc tính global NaN có giá trị đại diện cho khái niệm Not-A-Number (Không-phải-Số). - Theo MDN. 


Như vậy đủ để bạn hiểu hay chưa? Tôi thấy vẫn còn mơ hồ khi đọc. Để hiểu rõ hơn bạn có thể tìm hiểu từ "You don't know js", ở đó họ giải thích một cách rõ ràng hơn. 


Đại khái là NaN là theo nghĩa đen là viết tắt của "Not a Number" nhưng với mô tả này gây hiểu nhầm cho nên sẽ chính xác hơn nhiều nếu coi NaN là "Number không hợp lệ" thì có vẻ tường minh hơn. Như vậy, chúng ta có thể hiểu là NaN chính là một giá trị mà giá trị đó là kiểu số. 


Vậy câu hỏi đặt ra là làm thế nào để đánh giá một giá trị có phải là NaN hay không?


isNaN JavaScript


Vì sao lại có isNaN(), bạn hãy xem một code nhỏ dưới đây


NaN === NaN; //false

Ngay cả khi so sánh với bản thân nó mà vẫn return về false, lý do rất đơn giản là "NaN được đặc tả là không bao giờ bằng với một đối tượng hay một giá trị nào đó". Nếu bạn là một người tìm tòi và học hỏi thì câu trả lời nằm đây "Why is NaN === NaN false?"


Chính vì vậy isNaN() ra đời để làm việc đó. Chúng ta cần một hàm đặc biệt để xác định xem một giá trị có phải là NaN hay không. isNaN() Hóa ra là như vậy. Sửa lại ví dụ trên


isNaN(NaN); // true

Có vẻ trơn tru nhưng nhìn lại ví dụ ở trên cùng hay xem

isNaN('Anonystick.com'); // true

isNaN(undefined); // true

isNaN({}); // true


Nhìn sơ qua chúng ta thấy không phải là giá trị NaN nhưng vẫn return về true. Ngộ thật. Mà ngộ nha, BUG này tồn tại lâu rồi, nhưng giờ vần vậy. Chính vì vậy, những ai theo dõi blog javascript thì có thể thấy kể từ khi ES6 được Release thì có một phương pháp đó là Number.isNaN(). Có thể giúp chúng ta fix bug trong javascript này.


Number.isNaN(NaN); // true

Number.isNaN('Anonystick'); // false

Number.isNaN(undefined); // false

Number.isNaN({}); // false

Nhìn lại ví dụ trên, bạn có thể hiểu vấn đề đã được khắc phục.


Polyfill Number.isNaN ()


Giả sử nếu bạn đã miss cơ hội học những tính năng ES6 javascript cực kỳ quan trọng thì có lẽ bạn đã bị lỗi thời. Thế nhưng, tôi sẽ giúp bạn giải quyết vấn đề này, nhưng tôi khuyên bạn nên học lại ES6 tới ES12. Tại sao lại cần viết polyfill thì chúng ta đã thảo luận ở bài trước.


if (!Number.isNaN) {
  Number.isNaN = function(n) {
    return (
      typeof n === "number" &&
      window.isNaN( n )
    );
  };
}

Có một cách triển khai đơn giản hơn

if (!Number.isNaN) {
    Number.isNaN = function(n) {
        return n !== n;
    };
}

Tóm lại


Number.isNaN() sinh ra từ ES6 để giải quyết BUG tồn tại trên 20 năm qua của javascript. Đó là lý do, vì sao chúng ta nên sử dụng và tham khảo những cú pháp mới nhất của ES6 tới ES11 kể từ khi nó ra đời.

Có thể bạn đã bị missing