Skip to Content
Course content

248: isNaN vs Number.isNaN

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I want to show you a snippet of code that looks perfectly reasonable at first glance. Imagine you're building a simple price calculator where you take a value from a user input and check if it's valid before doing some math.

function processPayment(amount) {
  if (isNaN(amount)) {
    console.log("Invalid input: Please enter a numeric value.");
    return;
  }
  console.log(`Processing payment of $${amount}...`);
}

processPayment(100);      // "Processing payment of $100..."
processPayment("100");    // "Processing payment of $100..."
processPayment("hello");  // "Invalid input: Please enter a numeric value."
processPayment(undefined); // "Invalid input: Please enter a numeric value."

Everything seems to be working. You're catching the "bad" data. But here is where the bug creeps in. What happens if the amount is an empty string or null? In a real-world app, these often happen when a user clears a form field.

processPayment("");    // "Processing payment of $0..."
processPayment(null);    // "Processing payment of $0..."

Wait, what? An empty string isn't a valid payment amount, but isNaN("") returns false. This is a classic JavaScript "gotcha" that has probably caused more headaches than I care to count.

The Trap of Global Coercion

The problem is that the global isNaN() function is a bit too "helpful." Before it checks if a value is NaN, it tries to convert that value into a number first. This is called coercion.

When you pass "" (an empty string) into isNaN(), JavaScript coerces it into a number. And in the weird world of JavaScript coercion, Number("") is 0. Since 0 is a valid number, isNaN(0) is false. The same thing happens with null, which also coerces to 0.

Essentially, the global isNaN() doesn't actually ask "Is this value NaN?" Instead, it asks "Can this value not be turned into a number?" That's a huge difference when you're trying to debug data types.

Strictness with Number.isNaN

To fix this, we use Number.isNaN(). This was introduced in ES6 specifically to solve the coercion mess. Unlike the global version, Number.isNaN() does not coerce its argument. It only returns true if the value is actually the value NaN and its type is Number.

Let's rewrite our validator to be more explicit. Usually, if we're worried about empty strings or nulls, we should check for those first, and use Number.isNaN() to catch actual mathematical failures (like 0 / 0).

function processPayment(amount) {
  // First, we handle the types we know are invalid for payments
  if (amount === "" || amount === null) {
    console.log("Invalid input: Field cannot be empty.");
    return;
  }

  // Then we check if the result of any coercion is actually NaN
  if (Number.isNaN(Number(amount))) {
    console.log("Invalid input: Please enter a numeric value.");
    return;
  }
  
  console.log(`Processing payment of $${amount}...`);
}

processPayment("");    // "Invalid input: Field cannot be empty."
processPayment(null);  // "Invalid input: Field cannot be empty."
processPayment("abc"); // "Invalid input: Please enter a numeric value."

By using Number(amount) explicitly and then passing that result into Number.isNaN(), we've taken control of the coercion process. We're no longer guessing what the global isNaN is doing behind the scenes. I always recommend Number.isNaN() over the global version because it's predictable. In software engineering, predictable is always better than "helpful."




📋 Practical Task

Build a Math-Error Guard

You are building a scientific calculator module. Some operations (like dividing zero by zero or calculating the square root of a negative number) result in NaN. You need to create a guard function that differentiates between a "Math Error" (actual NaN) and "Invalid Input" (something that isn't a number at all, like a string).

Requirements:

  • Create a function called categorizeResult(value).
  • If the value is exactly NaN, return the string "Math Error".
  • If the value is not a number (e.g., a string, boolean, or undefined), return the string "Invalid Input".
  • If the value is a valid number, return the string "Success".
  • Use Number.isNaN() to ensure you are correctly identifying the actual NaN value without accidental coercion.

Test your function with these cases:

categorizeResult(NaN);          // Should return "Math Error"
categorizeResult(0 / 0);           // Should return "Math Error"
categorizeResult("hello");         // Should return "Invalid Input"
categorizeResult(undefined);       // Should return "Invalid Input"
categorizeResult(42);              // Should return "Success"
Rating
0 0

There are no comments for now.

to be the first to leave a comment.