Table of Contents#
- How
parseIntWorks: A Quick Refresher - Understanding Radix: What Is It, and Why Does It Matter?
- Case Study 1: Why
parseInt(8, 3)ReturnsNaN - Case Study 2: Why
parseInt(16, 3)Returns1 - The Key Difference: Valid vs. Invalid Leading Digits
- Common Pitfalls with
parseIntand Radix - Best Practices for Using
parseInt - Conclusion
- References
How parseInt Works: A Quick Refresher#
Before diving into radix, let’s recap how parseInt functions. The syntax is:
parseInt(string, radix);string: The value to parse (coerced to a string if not already one).radix(optional): An integer between 2 and 36 representing the base of the numeral system to use. If omitted,parseIntguesses the base (more on this later—but never rely on this!).
Core Behavior:
parseInt parses the string from left to right, extracting digits that are valid for the specified radix. It stops parsing at the first invalid character (including non-digit characters, or digits larger than the radix allows). If no valid digits are found (even in the first position), it returns NaN. Otherwise, it converts the valid prefix of the string to a decimal (base 10) integer.
Understanding Radix: What Is It, and Why Does It Matter?#
The radix (or base) defines the numeral system used to interpret the string argument. For example:
- Radix 10: Decimal (digits
0-9). - Radix 2: Binary (digits
0-1). - Radix 16: Hexadecimal (digits
0-9,A-F).
For a given radix r, valid digits are 0 to r-1. For example:
- Radix 3: Valid digits are
0,1,2(since3-1 = 2). Any digit ≥ 3 is invalid.
This is critical for our examples: both use radix = 3, so only 0, 1, and 2 are valid digits.
Case Study 1: Why parseInt(8, 3) Returns NaN#
Let’s dissect parseInt(8, 3) step by step:
Step 1: Coerce the Input to a String#
The first argument is 8, which JavaScript coerces to the string "8".
Step 2: Check for Valid Digits in Radix 3#
Radix 3 only allows digits 0, 1, 2. The first (and only) character in "8" is "8", which is invalid for radix 3 (since 8 > 2).
Step 3: No Valid Digits → Return NaN#
Since parseInt cannot find any valid digits to parse (the first character is already invalid), it returns NaN.
Case Study 2: Why parseInt(16, 3) Returns 1#
Now let’s analyze parseInt(16, 3):
Step 1: Coerce the Input to a String#
The first argument is 16, which coerces to the string "16".
Step 2: Parse Left-to-Right, Stopping at Invalid Digits#
- First character:
"1". In radix 3,1is a valid digit (since1 ≤ 2). - Second character:
"6". In radix 3,6is invalid (since6 > 2).
parseInt stops parsing at the first invalid character ("6") and keeps only the valid prefix: "1".
Step 3: Convert the Valid Prefix to Decimal#
Now, convert "1" (from radix 3) to decimal:
- For a single digit
din radixr, the decimal value isd * r⁰. - Here:
1 * 3⁰ = 1 * 1 = 1.
Thus, parseInt(16, 3) returns 1.
The Key Difference: Valid vs. Invalid Leading Digits#
The discrepancy between parseInt(8, 3) (returns NaN) and parseInt(16, 3) (returns 1) boils down to whether the first character is a valid digit for the radix:
parseInt(8, 3): The first character ("8") is invalid. No valid digits are parsed →NaN.parseInt(16, 3): The first character ("1") is valid.parseIntparses it, then stops at the next invalid character ("6"). The valid prefix ("1") is converted to decimal →1.
Common Pitfalls with parseInt and Radix#
Even experienced developers trip over parseInt’s behavior. Here are key pitfalls to avoid:
1. Forgetting to Specify the Radix#
If you omit the radix, parseInt guesses the base:
- If the string starts with
"0x", it uses radix 16. - If the string starts with
"0", it used to use radix 8 (octal) in older browsers (now deprecated, but still risky). - Otherwise, it defaults to radix 10.
Example: parseInt("08") may return 0 (octal) in legacy code, but 8 in modern browsers. Always specify the radix!
2. Ignoring Invalid Digits Mid-String#
As we saw with parseInt(16, 3), parseInt stops at the first invalid digit but still parses the valid prefix. This can lead to unexpected results if you assume the entire string is valid.
3. Non-String Inputs#
parseInt coerces non-string inputs to strings, which can cause confusion. For example:
parseInt(true, 3); // Coerces to "true" → first character "t" is invalid → NaNBest Practices for Using parseInt#
To avoid bugs with parseInt, follow these practices:
- Always Specify the Radix: Explicitly pass a radix (e.g.,
parseInt(str, 10)for decimal) to avoid ambiguous behavior. - Validate Inputs: Check that the string contains only valid digits for the radix before parsing (e.g., use a regex like
/^[0-2]+$/for radix 3). - Beware of Coercion: If the input isn’t a string, explicitly convert it first (e.g.,
String(num)) to make behavior predictable. - Handle
NaNGracefully: Check if the result isNaNand handle invalid inputs (e.g.,if (isNaN(result)) { throw new Error("Invalid number"); }).
Conclusion#
The mystery of parseInt(8, 3) returning NaN and parseInt(16, 3) returning 1 is solved by understanding how parseInt parses strings with a specified radix:
- It parses left-to-right, stopping at the first invalid digit.
- If no valid digits are found (even in the first position), it returns
NaN. - Otherwise, it converts the valid prefix to decimal.
By mastering radix behavior and following best practices like specifying the radix, you’ll avoid common parseInt pitfalls and write more robust JavaScript code.