How to check if a value is NaN in JavaScript
Checking for NaN values is crucial for input validation, error handling, and mathematical operations in JavaScript applications.
With over 25 years of experience in software development and as the creator of CoreUI, I’ve implemented NaN checking extensively in components like calculators, form validators, and data processors.
The most accurate and recommended approach is Number.isNaN(), which performs a strict NaN check without type coercion.
This method is precise, avoids the common pitfalls of the older isNaN() function, and is supported in all modern browsers.
Use Number.isNaN() to check if a value is specifically NaN without type coercion.
const result = 0 / 0
Number.isNaN(result) // true
const text = 'hello'
Number.isNaN(text) // false — string is not NaN, just not a number
Number.isNaN() returns true only when the value is the actual NaN primitive. This strict behavior prevents the false positives that plague the global isNaN(), which coerces its argument first.
1. Number.isNaN() vs global isNaN()
The global isNaN() converts the argument to a number before testing. This means non-numeric strings and other types incorrectly return true.
// Global isNaN — coerces before checking
isNaN('hello') // true ← false positive: 'hello' is not NaN
isNaN(undefined) // true ← false positive
isNaN('') // false ← empty string coerces to 0
// Number.isNaN — no coercion
Number.isNaN('hello') // false ✓
Number.isNaN(undefined) // false ✓
Number.isNaN(NaN) // true ✓
Always prefer Number.isNaN() in modern code. The global isNaN() exists mainly for legacy compatibility.
2. Detecting Invalid Math Results
Division by zero and operations on non-numeric values produce NaN. Checking the result before using it prevents downstream errors.
function safeDivide(a, b) {
const result = a / b
if (Number.isNaN(result)) {
return 0 // or throw, or return null depending on context
}
return result
}
safeDivide(10, 2) // 5
safeDivide(0, 0) // 0 (guarded)
safeDivide(10, 0) // Infinity — note: not NaN, a separate case
Other sources of NaN from math: Math.sqrt(-1), parseInt('abc'), parseFloat('xyz'), and Number('not a number').
3. Validating Numeric Form Inputs
When reading a value from a text input and converting it to a number, the result is NaN if the user typed non-numeric content. Always guard before using the value.
function getNumericInput(inputElement) {
const value = parseFloat(inputElement.value)
if (Number.isNaN(value)) {
console.warn('Invalid numeric input')
return null
}
return value
}
// Usage
const qty = getNumericInput(document.getElementById('quantity'))
if (qty !== null) {
updateCart(qty)
}
This pattern is essential for any form that feeds into calculations — pricing, quantities, coordinates, and so on. See the CoreUI form validation docs for how to combine this with visual feedback.
4. Processing API Responses
External APIs occasionally return null, empty strings, or missing fields instead of numbers. Convert and validate before use.
function parseApiPrice(raw) {
const price = Number(raw)
if (Number.isNaN(price)) {
return 0
}
return price
}
parseApiPrice('12.99') // 12.99
parseApiPrice(null) // 0
parseApiPrice('') // 0
parseApiPrice('N/A') // 0
Number(null) is 0 and Number('') is 0, so those cases pass through cleanly. Only truly non-numeric strings like 'N/A' or 'undefined' produce NaN.
5. Checking Whether a Value Can Convert to a Valid Number
Sometimes you want to know if a value is “usable as a number”, even if it is currently a string. In that case combine Number() with isNaN() (global is fine here, since you are explicitly converting first).
function isNumeric(value) {
return !isNaN(Number(value))
}
isNumeric('42') // true
isNumeric('3.14') // true
isNumeric('') // true ← empty string → 0; adjust if unwanted
isNumeric('hello') // false
isNumeric(null) // true ← null → 0; adjust if unwanted
For stricter intent, trim the string and reject empty values explicitly:
function isStrictlyNumeric(value) {
if (typeof value === 'string' && value.trim() === '') return false
return !Number.isNaN(Number(value))
}
6. Using Object.is() as an Alternative
Object.is(value, NaN) is another strict option. Unlike ===, it correctly handles the fact that NaN !== NaN.
Object.is(NaN, NaN) // true
Object.is(0 / 0, NaN) // true
Object.is('hello', NaN) // false
// For comparison: NaN === NaN is always false
NaN === NaN // false
Object.is() is useful when you need to distinguish +0 from -0 in the same check, but for typical NaN detection Number.isNaN() is clearer in intent.
7. Filtering NaN Values from Arrays
When processing datasets, you often need to strip out NaN entries before aggregating.
const readings = [12, NaN, 7, NaN, 3]
const valid = readings.filter(v => !Number.isNaN(v))
// [12, 7, 3]
const total = valid.reduce((sum, v) => sum + v, 0)
// 22
Alternatively, replace NaN with a default before filtering:
const sanitized = readings.map(v => Number.isNaN(v) ? 0 : v)
// [12, 0, 7, 0, 3]
Best Practice Note:
Always use Number.isNaN() over the global isNaN() in modern code — the coercion behavior of the global function causes subtle bugs that are hard to trace.
For the common question of “can this value be used as a number”, combine Number() conversion with a NaN check rather than relying on typeof alone.
We apply these patterns throughout CoreUI’s JavaScript utilities to ensure reliable numeric handling across all components.



