Lập trình · 23/10/2026

JavaScript isNaN và Number.isNaN: vì sao trả false vẫn chưa phải số hợp lệ?

Điều kiện !isNaN(value) có thể chấp nhận chuỗi rỗng hoặc null; còn !Number.isNaN(value) có thể chấp nhận cả chuỗi không chứa số. Hai hàm trả lời hai câu hỏi khác nhau. Không nên coi kết quả false là bằng chứng đầu vào đã đạt schema số của ứng dụng.

JavaScript isNaN và Number.isNaN: vì sao trả false vẫn chưa phải số hợp lệ?

Điều kiện !isNaN(value) có thể chấp nhận chuỗi rỗng hoặc null; còn !Number.isNaN(value) có thể chấp nhận cả chuỗi không chứa số. Hai hàm trả lời hai câu hỏi khác nhau. Không nên coi kết quả false là bằng chứng đầu vào đã đạt schema số của ứng dụng.

1. isNaN có ép kiểu, Number.isNaN thì không

console.log(isNaN('hello')); // true
console.log(Number.isNaN('hello')); // false
console.log(isNaN('')); // false
console.log(isNaN(null)); // false
console.log(Number.isNaN(NaN)); // true

isNaN toàn cục chuyển đầu vào sang Number rồi kiểm tra kết quả. Chuỗi rỗng và null chuyển thành 0 nên cho false. Number.isNaN không chuyển kiểu: chỉ nhận diện giá trị NaN thuộc kiểu number.

Vì 'hello' không phải giá trị NaN, Number.isNaN('hello') trả false là đúng chức năng. Đổi máy móc isNaN thành Number.isNaN trong validator có thể làm chuỗi đó đi qua một nhánh kiểm tra vốn đang mong số. Trước khi thay, xác định đang kiểm tra giá trị NaN hay kiểm tra đầu vào số.

2. “Không phải NaN” chưa có nghĩa hữu hạn hoặc đúng kiểu

console.log(Number.isNaN(Infinity)); // false
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite('12')); // false
console.log(Number.isFinite(12)); // true
console.log(isNaN('12')); // false
console.log('12' + 1); // 121

Number.isFinite yêu cầu đầu vào là number và không phải NaN hay hai dạng Infinity. Trong ví dụ cuối, chuỗi '12' không bị isNaN từ chối nhưng phép + vẫn nối chuỗi. Một phép kiểm tra không tự thay đổi kiểu của biến được truyền vào.

Nếu nguồn dữ liệu là ô nhập văn bản, cần bước phân tích chuỗi riêng với quy tắc về dấu thập phân, khoảng trắng và miền giá trị. Nếu API đã quy định field là number, từ chối chuỗi số có thể giúp phát hiện sai schema sớm hơn thay vì sửa ngầm.

3. Kết hợp kiểu số hữu hạn với miền nghiệp vụ

function readScore(value) {
  if (!Number.isFinite(value)) {
    throw new TypeError('score must be a finite number');
  }
  if (value < 0 || value > 100) {
    throw new RangeError('score must be between 0 and 100');
  }
  return value;
}
console.log(readScore(0)); // 0
console.log(readScore(87.5)); // 87.5
console.log(readScore(100)); // 100

Contract minh họa nhận điểm số từ 0 đến 100, gồm cả số thập phân. Helper không ép kiểu, không làm tròn và không dùng giá trị mặc định. Các yêu cầu như chỉ chấp nhận số nguyên hoặc bước điểm 0,5 cần được kiểm tra thêm nếu sản phẩm quy định.

Giới hạn 0–100 là lựa chọn của ví dụ, không phải quy tắc JavaScript. Number.isFinite cũng không bảo đảm mọi phép tính tiếp theo hợp lệ; sau một phép biến đổi, kiểm tra kết quả nếu contract yêu cầu. Đầu vào đúng chưa chứng minh toàn bộ công thức đúng.

4. Tách dữ liệu thiếu khỏi số 0

Nếu field được phép thiếu, xử lý trạng thái thiếu riêng trước khi gọi helper. Không tự đổi null hoặc chuỗi rỗng thành điểm 0 nếu sản phẩm chưa quy định, vì “chưa có kết quả” và “kết quả bằng 0” có thể dẫn tới quyết định khác nhau.

Khi nâng cấp validator đang chạy, thống kê mẫu dữ liệu hợp lệ theo contract cũ và mới bằng dữ liệu kiểm thử. Trả lỗi rõ ràng cho bên gửi khi đổi chính sách; tránh để frontend chấp nhận chuỗi số trong khi backend chỉ nhận number mà không có bước chuyển đổi được thống nhất.

5. Checklist trước khi dùng isNaN để xác thực

  • Cần nhận diện NaN hay xác thực toàn bộ trường số?
  • Đầu vào number hay chuỗi cần phân tích?
  • NaN, Infinity và giá trị thiếu được xử lý thế nào?
  • Số 0 và các giá trị biên có hợp lệ không?
  • Có yêu cầu số nguyên, bước nhảy hoặc làm tròn riêng?

Sáu khối mã Việt–Anh đã chạy bằng Node.js; kiểm tra bổ sung đầu vào sai kiểu, số không hữu hạn và ranh giới 0–100 của helper. Chưa tích hợp form hoặc API thực tế.

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.