JavaScriptNumber Methods

Number Methods

JavaScript provides two flavours of number tooling. Static methods on the Number constructor (Number.parseInt, Number.isFinite, …) inspect or convert values. Instance methods on every number (toFixed, toString, toPrecision) format the value you already have. Knowing which is which — and which legacy global to avoid — saves a lot of subtle bugs.

Parsing strings into numbers

Three common tools, with three different temperaments:

JS
Number("42");          // 42        — whole string must parse, else NaN
Number("42px");        // NaN
Number("");            // 0          — surprise!
Number("  3.14  ");    // 3.14       — trims whitespace
Number(null);          // 0          — gotcha
Number(undefined);     // NaN
Number(true);          // 1
Number(false);         // 0

Number.parseInt("42px");      // 42         — stops at the first non-digit
Number.parseInt("0.7");       // 0          — never reads past the dot
Number.parseInt("10", 2);     // 2          — second arg = radix (base)
Number.parseInt("0xff");      // 255        — recognises hex prefix
Number.parseInt("hello");     // NaN

Number.parseFloat("3.14abc"); // 3.14
Number.parseFloat("1e3");     // 1000
Number.parseFloat(".5");      // 0.5
Number.parseFloat("abc");     // NaN
Always pass a radix
`Number.parseInt(value, 10)` makes your intent explicit and dodges old engines that interpreted a leading zero as octal. Most linters require it.

The unary + operator is a fast equivalent of Number(...) and is idiomatic for "this should be a number":

JS
+"42";       // 42
+"3.14";     // 3.14
+"";         // 0
+"abc";      // NaN
+true;       // 1
+null;       // 0
Number.isFinite, isInteger, isNaN, isSafeInteger

The static Number.is* methods are the modern, type-safe replacements for the global isFinite and isNaN functions. They never coerce — if you pass a string, they return false immediately.

JS
Number.isFinite(42);         // true
Number.isFinite(Infinity);   // false
Number.isFinite(NaN);        // false
Number.isFinite("42");       // false — does not coerce

isFinite("42");              // true  — global version coerces! avoid

Number.isInteger(7);         // true
Number.isInteger(7.0);       // true   (still an integer in IEEE 754)
Number.isInteger(7.1);       // false
Number.isInteger("7");       // false  — no coercion

Number.isNaN(NaN);           // true
Number.isNaN("NaN");         // false  — only true for real NaN
isNaN("NaN");                // true   — global version coerces, gotcha

Number.isSafeInteger(2 ** 53 - 1);  // true
Number.isSafeInteger(2 ** 53);      // false — past safe range
Prefer Number.isNaN over global isNaN
The global `isNaN` converts its argument to a number first, so `isNaN("hello")` is `true` (because `Number("hello")` is `NaN`). `Number.isNaN` returns `true` only for the actual `NaN` value.
Formatting with toFixed, toPrecision, toString

These are instance methods — call them on a number value. They return strings, never new numbers, which is exactly what you want for display.

JS
const x = 3.14159;

x.toFixed(0);        // "3"
x.toFixed(2);        // "3.14"
x.toFixed(4);        // "3.1416"
(2).toFixed(2);      // "2.00"   — pads with zeros

x.toPrecision(2);    // "3.1"     — significant digits
x.toPrecision(5);    // "3.1416"
(0.000123).toPrecision(2); // "0.00012"

(255).toString();    // "255"
(255).toString(2);   // "11111111"   — binary
(255).toString(16);  // "ff"         — hex
(255).toString(8);   // "377"        — octal
(0.5).toString();    // "0.5"

(1234567).toExponential(2); // "1.23e+6"
Why the parentheses?
`5.toString()` is a syntax error because the parser sees `5.` as a number literal. Write `(5).toString()` or `5..toString()` or store the number in a variable.
Rounding with toFixed is not banker's rounding

toFixed uses the same flawed rounding as your floats:

JS
(1.005).toFixed(2);   // "1.00"  — expected "1.01"
(1.015).toFixed(2);   // "1.01"
(1.235).toFixed(2);   // "1.24"

The value 1.005 is actually stored as 1.00499999..., so it rounds down. For correct currency rounding, multiply, Math.round, then divide — or work in cents from the start.

JS
function round2(n) {
  return Math.round((n + Number.EPSILON) * 100) / 100;
}

round2(1.005); // 1.01
Locale-aware formatting

For anything a user actually reads — prices, percentages, large counts — use toLocaleString or the more capable Intl.NumberFormat. They handle thousands separators, decimal commas, currency symbols and grouping per locale.

JS
const price = 1234567.89;

price.toLocaleString("en-US");  // "1,234,567.89"
price.toLocaleString("de-DE");  // "1.234.567,89"
price.toLocaleString("hi-IN");  // "12,34,567.89"

price.toLocaleString("en-US", {
  style: "currency",
  currency: "USD",
});                              // "$1,234,567.89"

new Intl.NumberFormat("en-US", {
  style: "percent",
  maximumFractionDigits: 1,
}).format(0.4567);              // "45.7%"
Cheat-sheet
  • Parse a user input stringNumber.parseFloat(value) or Number(value) and check the result with Number.isFinite.

  • Test for a real NaNNumber.isNaN(value) (never value === NaN).

  • Test for a real, finite, safe integerNumber.isInteger or Number.isSafeInteger.

  • Round to N decimal places for displayvalue.toFixed(N) (remember it returns a string).

  • Round correctly for money — work in integer cents, or Math.round((v + Number.EPSILON) * 100) / 100.

  • Format for a humanIntl.NumberFormat with the right locale and style.

Most number bugs come from mixing the legacy globals (isNaN, parseInt) with the modern static methods. Default to the Number.-prefixed versions and your code becomes immune to a surprising number of quiet coercion traps.