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:
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"); // NaNThe unary + operator is a fast equivalent of Number(...) and is idiomatic for "this should be a number":
+"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.
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 rangeFormatting 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.
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"
Rounding with toFixed is not banker's rounding
toFixed uses the same flawed rounding as your floats:
(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.
function round2(n) {
return Math.round((n + Number.EPSILON) * 100) / 100;
}
round2(1.005); // 1.01Locale-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.
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 string —
Number.parseFloat(value)orNumber(value)and check the result withNumber.isFinite.Test for a real
NaN—Number.isNaN(value)(nevervalue === NaN).Test for a real, finite, safe integer —
Number.isIntegerorNumber.isSafeInteger.Round to N decimal places for display —
value.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 human —
Intl.NumberFormatwith 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.