JavaScript • Syntax and Core Types

Handling NaN & Parsing Numbers — Handle NaN and parse numeric strings (parseInt/parseFloat) (intro)

Learn to detect failed math operations and safely convert text into usable numbers in JavaScript.

JavaScript emblem with code brackets, braces, and a code file.
Inside this lesson 10 sections 5 questions 9 figures

SECTION 1

Historical Context & Motivation

Every programming language needs a way to handle situations where a calculation goes wrong—like dividing zero by zero, or trying to multiply a word by a number. In mathematics, these operations are simply "undefined," but a running computer program can't just stop and shrug. It needs a value to place in memory so execution can continue. The concept of NaN (short for Not-a-Number) was created to fill exactly that role.

At the same time, web pages constantly receive data as text—from form fields, URLs, and server responses. A user typing "42" into a text box produces a string, not an actual number. JavaScript needed built-in tools—parseInt and parseFloat—to convert those text strings into numbers the language can do math with.

1985 • IEEE 754 Standard Published

The Institute of Electrical and Electronics Engineers releases the IEEE 754 standard for floating-point arithmetic, formally defining NaN as a special value that represents undefined or unrepresentable numeric results.

1995 • JavaScript Is Born

Brendan Eich creates JavaScript in just 10 days at Netscape. The language adopts IEEE 754 double-precision floating-point numbers and inherits the NaN value, along with helper functions like parseInt() and parseFloat() for parsing user input.

1999 • ECMAScript 3 Formalizes isNaN()

The third edition of the ECMAScript specification codifies the global isNaN() function, giving developers a standard way to check whether a value is NaN.

2015 • ES6 Introduces Number.isNaN()

ECMAScript 2015 (ES6) adds Number.isNaN(), a stricter check that fixes quirks in the original isNaN() function, making NaN detection more reliable.

The central question this lesson addresses is straightforward: when JavaScript encounters text that looks like a number—or an operation that produces no valid numeric result—how do you detect it, handle it, and convert it safely? Mastering these tools is essential for writing programs that don't crash or produce mysterious bugs when real-world data isn't perfectly clean.

SECTION 2

Core Principles & Definitions

Before diving into code, let's establish the foundational ideas behind NaN and number parsing. These concepts show up constantly in real JavaScript programs, so understanding them clearly now will save you many hours of debugging later.

1

NaN — Not-a-Number

A special numeric value JavaScript uses when a math operation fails or when a conversion to a number is impossible. Despite its name, typeof NaN returns "number"—it's technically a number type that signals 'something went wrong.'
2

NaN Is Never Equal to Itself

The expression NaN === NaN returns false. This is the only value in JavaScript (and in IEEE 754) that is not equal to itself. You must use isNaN() or Number.isNaN() to test for it.
3

parseInt() — Parse to Integer

Reads a string from left to right, extracts as many leading digits as it can, and returns a whole number (integer). It stops parsing at the first character that isn't a valid digit. If no digits are found at all, it returns NaN.
4

parseFloat() — Parse to Decimal

Works like parseInt() but also recognizes a decimal point, so it can return numbers with fractional parts like 3.14. It ignores trailing non-numeric characters just like parseInt().
5

The Radix Parameter

parseInt() accepts an optional second argument called the radix (base). Always pass 10 for decimal numbers to avoid unexpected behavior with strings that start with "0" or "0x".
✦

KEY TAKEAWAY

Think of NaN like a "CHECK ENGINE" light on a car dashboard. The car (your program) is still running, but something under the hood didn't work as expected. You can't fix the problem by comparing the light to itself—you need a diagnostic tool (isNaN() or Number.isNaN()) to detect it and decide what to do next.

SECTION 3

Visual Explanation — How Parsing Works

The diagram below shows how parseInt() and parseFloat() process a string character by character from left to right. Understanding this left-to-right scanning behavior is the key to predicting what these functions return.

How parseInt("42px", 10) Scans a String"4"index 0"2"index 1"p"index 2"x"index 3Scanner reads left → right✓ Valid digits: 4, 2✗ STOP at "p"RESULT42What if no digits found?parseInt("hello", 10)RESULTNaNparseFloat("3.14meters")3.14m→ stops → returns3.14
The scanner reads each character from left to right. Cyan-bordered boxes represent valid digit characters that get consumed. Red-bordered boxes mark where parsing stops. The yellow dot shows how parseFloat() also accepts the decimal point.

Notice the critical pattern: both functions are tolerant of trailing junk characters. The string "42px" successfully yields 42 because the parser grabs the leading digits and ignores the rest. However, if the very first character isn't a digit (or a sign like + or -), there are no digits to collect, and the result is NaN.

SECTION 4

How It Works — NaN Detection & Parsing Rules

Operations That Produce NaN

JavaScript produces NaN in several predictable situations. Attempting math with non-numeric values, such as "hello" * 3, returns NaN. Indeterminate arithmetic like 0 / 0 also yields NaN. And calling parseInt() or parseFloat() on a string with no leading digits returns NaN as well. Once NaN appears in a calculation, it's "contagious"—any further math with NaN produces NaN.

Detecting NaN: Two Functions

GLOBAL isNaN()

isNaN(value)→convertsvaluetoNumberfirst,thenchecksisNaN(value) → converts value to Number first, then checks

The global isNaN() function first coerces its argument to a number, then checks if the result is NaN. This means isNaN("hello") returns true because Number("hello") is NaN. This can be confusing because "hello" isn't literally the NaN value—it's a string.

STRICT Number.isNaN()

Number.isNaN(value)→trueONLYifvalueisexactlyNaNNumber.isNaN(value) → true ONLY if value is exactly NaN

The stricter Number.isNaN() does no type coercion. It returns true only when the value is already the NaN value. So Number.isNaN("hello") returns false because the string "hello" is not the numeric value NaN.

parseInt() Syntax

parseInt SYNTAX

parseInt(string,radix)parseInt(string, radix)

string — the text to parse (leading whitespace is trimmed). radix — the base of the number system (2 for binary, 10 for decimal, 16 for hex). Always specify 10 for normal decimal parsing.

parseFloat SYNTAX

parseFloat(string)parseFloat(string)

string — the text to parse. Unlike parseInt, parseFloat does not accept a radix parameter because it always works in base 10. It recognizes one decimal point and exponent notation (e.g., "1.5e3" → 1500).

SECTION 5

Detailed Breakdown — Parsing Results at a Glance

The following table shows what different inputs produce when passed through parseInt(), parseFloat(), and Number(). Studying these examples side by side reveals the subtle differences between the three approaches. Pay special attention to how each one handles strings with mixed content.

InputparseInt(input, 10)parseFloat(input)Number(input)
"42"424242
"3.14"33.143.14
"42px"4242NaN
"$99.50"NaNNaNNaN
" 7 "777
""NaNNaN0
"0xFF"2550255
trueNaNNaN1

Comparison of three number-conversion approaches in JavaScript

Decision Flowchart: Choosing the Right ConversionGot a string value?Does it have trailing non-digits?YESNONeed a decimal result?Use Number(str)YESNOparseFloat()parseInt(s, 10)Always check the result with isNaN() before using it!
This flowchart helps you decide which conversion function to use. If the string might contain trailing units like "px" or "kg", use parseFloat or parseInt. If the string should be purely numeric, Number() is the strictest option.

SECTION 6

Worked Example — Parsing User Input

Imagine you're building a simple web app that calculates the total cost of items. The user types a price into a text field, and your code receives it as a string. Let's walk through parsing and validating that input step by step.

Parsing a Price from User Input

  1. 1

    Step 1 — Receive the Input

    The user types "19.99" into a form field. In JavaScript, the value from an HTML input element is always a string, even if it looks like a number. We store it in a variable: let userInput = "19.99";
    userInput is the string "19.99"
  2. 2

    Step 2 — Parse with parseFloat()

    Since we expect a price with decimal places, we use parseFloat() rather than parseInt() (which would chop off the cents). let price = parseFloat(userInput); The parser reads 1, 9, ., 9, 9 and converts them into the number 19.99.
    price = 19.99
  3. 3

    Step 3 — Validate with isNaN()

    Before using the price in a calculation, we check whether parsing succeeded. If the user had typed something like "free", parseFloat() would have returned NaN. if (isNaN(price)) { console.log("Please enter a valid number."); } else { console.log("Price accepted: $" + price); }
    Since price is 19.99 (not NaN), the output is: "Price accepted: $19.99"
  4. 4

    Step 4 — Calculate the Total

    Now we can safely use the number in arithmetic. Let's say the user wants 3 items: let quantity = parseInt("3", 10); let total = price * quantity; Notice we used parseInt() with radix 10 for the quantity because it's always a whole number.
    total = 59.97
  5. 5

    Step 5 — Handle Edge Cases

    What if the user typed "19.99 dollars"? Because parseFloat() ignores trailing text, it would still return 19.99. But Number("19.99 dollars") would return NaN because Number() demands the entire string be a valid number. Choose the function that matches how strict you need to be.
    parseFloat("19.99 dollars") → 19.99 (tolerant) vs. Number("19.99 dollars") → NaN (strict)

SECTION 7

Strengths, Pitfalls & Comparisons

Each number-conversion approach in JavaScript has distinct advantages and gotchas. The table below compares them so you can make informed choices in your own code.

FeatureparseInt(s, 10)parseFloat(s)Number(s)
Handles trailing textYes — ignores non-digit suffixYes — ignores non-numeric suffixNo — returns NaN
Returns decimalsNo — truncates to integerYesYes
Accepts radixYes (2–36)No (always base 10)Hex strings auto-detected
Empty string ""NaNNaN0 (surprising!)
Boolean trueNaNNaN1
Best use caseExtracting integers from messy strings (CSS values, IDs)Extracting decimal numbers from strings with unitsStrict, full-string conversion

Strengths and pitfalls of each conversion method

⚠

Common Pitfall

Forgetting the radix in parseInt() can produce unexpected results. In older JavaScript engines, parseInt("08") was treated as octal (base 8) and returned 0. Modern engines default to base 10, but always writing parseInt("08", 10) makes your intention clear and keeps your code safe across all environments.
✦

KEY TAKEAWAY

Think of parseInt() and parseFloat() like a metal detector scanning a beach—they pick up the first metallic object (digits) they find and ignore the sand (non-numeric characters) after it. Number() is more like airport security: everything in the string must pass inspection, or the whole thing gets rejected as NaN.

SECTION 8

Connection to Advanced Concepts

The parsing and NaN-handling skills you've learned here form the foundation for more advanced data processing patterns in JavaScript. As you move into topics like form validation, API data handling, and TypeScript, these ideas scale up significantly.

This Lesson (Intro)Advanced Topic
isNaN() and Number.isNaN()Defensive programming patterns: null checks, optional chaining (?.), and nullish coalescing (??)
parseInt() / parseFloat()Parsing JSON from APIs: JSON.parse() with custom reviver functions for type-safe data handling
Type coercion quirksTypeScript's static type system eliminates many coercion bugs at compile time by enforcing explicit type annotations
Basic input validationRegular expressions (RegExp) for complex pattern matching and input sanitization

How today's concepts connect to future JavaScript topics

As your projects grow more complex, you'll encounter data coming from databases, third-party APIs, and user inputs that can be wildly unpredictable. The habit of always validating and parsing before computing is one of the most important defensive programming skills you can develop. Every senior developer you'll meet will tell you: never trust incoming data—always check it first.

SECTION 9

Practice Problems

Test your understanding with these five problems. They progress from basic recall to critical thinking. Try to answer each one before reading the solution.

Question 1: CONCEPTUAL

Why does NaN === NaN return false in JavaScript? What function should you use instead to check if a value is NaN?
Show answer
NaN is defined by the IEEE 754 standard as a value that is not equal to anything, including itself. The reasoning is that NaN can result from many different failed operations (0/0, undefined math, bad parsing), so two NaN values don't necessarily represent the same failed computation. To check for NaN, you should use Number.isNaN(value) for a strict check, or the global isNaN(value) if you also want to detect values that would become NaN after type coercion.

Question 2: BASIC CALCULATION

What does each of the following expressions evaluate to? a) parseInt("100px", 10) b) parseFloat("7.5em") c) parseInt("abc", 10)
Show answer
a) 100 — parseInt reads the digits 1, 0, 0, then stops at the letter "p." b) 7.5 — parseFloat reads 7, the decimal point, and 5, then stops at "e" (which here is not part of exponent notation since it's followed by "m"). c) NaN — the very first character "a" is not a digit, so parseInt cannot extract any number at all and returns NaN.

Question 3: INTERMEDIATE

Explain the difference between isNaN("hello") and Number.isNaN("hello"). What does each return, and why?
Show answer
isNaN("hello") returns true because the global isNaN function first coerces the argument by calling Number("hello"), which produces NaN, and then checks that result. On the other hand, Number.isNaN("hello") returns false because Number.isNaN does not coerce its argument. The string "hello" is a string, not the numeric value NaN, so the strict check reports false. Use Number.isNaN when you specifically want to know if a value is already the NaN number.

Question 4: APPLIED

You are building a temperature converter. The user types a temperature like "72°F" into a text field. Write a short JavaScript code snippet that extracts the number 72, checks if parsing succeeded, and if so, converts it to Celsius using the formula C = (F − 32) × 5 / 9. If parsing fails, log an error message.
Show answer
Here's one solution: let input = "72°F"; let fahrenheit = parseFloat(input); if (isNaN(fahrenheit)) { console.log("Error: invalid temperature."); } else { let celsius = (fahrenheit - 32) * 5 / 9; console.log(celsius.toFixed(1) + "°C"); } We use parseFloat because temperatures can have decimals. It reads "72" and stops at the degree symbol. The isNaN check ensures we don't attempt math on a bad value. The result is approximately 22.2°C.

Question 5: CRITICAL THINKING

Consider this code: let x = parseInt("", 10); and let y = Number("");. What are the values of x and y? Why are they different? In what real-world scenario could this inconsistency cause a bug, and how would you guard against it?
Show answer
x is NaN because parseInt finds no digits to parse in an empty string. y is 0 because Number("") treats an empty string as zero—a design decision baked into the ECMAScript specification. This inconsistency could cause a bug in a shopping cart: if a user clears a quantity field (making it empty) and you use Number("") to read it, the system silently calculates a $0 total instead of showing an error. To guard against this, you can check for an empty string before conversion: if (input.trim() === "") { /* show error */ }. Alternatively, use parseInt or parseFloat, which correctly return NaN for empty strings.

SUMMARY

Lesson Summary

Summary

NaN (Not-a-Number) is JavaScript's way of signaling that a numeric operation failed. It's unique because it is never equal to itself, so you must detect it using isNaN() (which coerces first) or the stricter Number.isNaN() (which checks without coercion). NaN is "contagious"—once it enters a calculation, every subsequent result becomes NaN too.

To convert strings into numbers, use parseInt(string, 10) for whole numbers and parseFloat(string) for decimals. Both scan left-to-right and tolerate trailing non-numeric characters, making them ideal for messy real-world input. For strict full-string conversion, use Number(). Always validate the result with an isNaN check before using it in calculations to prevent silent bugs in your programs.

Varsity Tutors • JavaScript • Handling NaN & Parsing Numbers