Number.prototype.toString()

Converts a number to a string, optionally in any base from 2 to 36.

Signature
toString()
toString(radix)

Parameters

ParameterTypeDescription
$radixoptionalnumber= 10An integer base between 2 and 36 to represent the number in. Digits above 9 use the letters a–z.

Return value

stringA string representing the number in the given base. When radix is 10, scientific notation is used if the magnitude is 10^21 or greater, or less than 10^-6.

Errors

Throws a RangeError if radix is less than 2 or greater than 36, and a TypeError if called on a value that is not a number.

Called with no argument this is the conversion that already happens implicitly in template literals and string concatenation, so you rarely need to write it. The reason to call it explicitly is the radix: (255).toString(16) is "ff", (5).toString(2) is "101". It is the inverse of parseInt() with the same base.

Negative numbers are not two's complement

This surprises people coming from C. (-10).toString(2) is "-1010" — a minus sign followed by the magnitude, not a bit pattern. If you want the 32-bit two's-complement representation, force the value through a bitwise operator first: (-10 >>> 0).toString(2).

Fractions and big values

Non-integers are supported in any base: (0.5).toString(2) is "0.1". In base 10, magnitudes at or above 1021 or below 10-6 come back in exponential form — (1e21).toString() is "1e+21" — which will break a naive string parser downstream.

When to reach for it

Hex colour values, bitmask debugging, compact base-36 identifiers, and any place you need to see the raw bits of a flag word. Pad the result yourself with padStart(); toString() never adds leading zeros.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Print a bitmask in binary while debugging flag logic
  • Convert an RGB component to a two-character hex string
  • Generate a short base-36 identifier from a counter

Frequently asked questions

How do I convert a number to binary in JavaScript?

Call n.toString(2). For negative values use (n >>> 0).toString(2) to get the 32-bit two's-complement pattern instead of a signed "-1010" style string.

Why does toString() give me "1e+21" instead of digits?

In base 10, magnitudes at or above 1e21 and below 1e-6 are rendered in exponential notation. Use toFixed() or BigInt for large integers you need in full decimal form.

What is the maximum radix toString() accepts?

36, using digits 0-9 then letters a-z. Anything below 2 or above 36 throws a RangeError.

More examples

Building a hex colour string

toString(16) drops leading zeros, so padStart(2, '0') is mandatory — without it, a component of 0 would collapse the string to four characters.

Example · javascript
function rgbToHex(r, g, b) {
  return '#' + [r, g, b]
    .map((c) => c.toString(16).padStart(2, '0'))
    .join('');
}

console.log(rgbToHex(255, 128, 0)); // "#ff8000"
console.log(rgbToHex(0, 0, 0)); // "#000000"
console.log(rgbToHex(18, 52, 86)); // "#123456"

Round-tripping with parseInt

Every base round-trips exactly for integers, which is what makes base 36 a safe compact encoding for numeric ids.

Example · javascript
const n = 1234567;

for (const radix of [2, 8, 16, 36]) {
  const s = n.toString(radix);
  console.log(radix, s, Number.parseInt(s, radix) === n);
}
// 2  "100101101011010000111" true
// 8  "4553207"              true
// 16 "12d687"               true
// 36 "qglj"                 true

Where base 10 changes shape

The switch to exponential form happens at 1e21 and below 1e-6, so string handling that assumes plain digits needs a guard at those boundaries.

Example · javascript
console.log((1e20).toString()); // "100000000000000000000"
console.log((1e21).toString()); // "1e+21"
console.log((0.000001).toString()); // "0.000001"
console.log((0.0000001).toString()); // "1e-7"

try {
  (255).toString(37);
} catch (err) {
  console.log(err.name); // "RangeError"
}

Discussion

  • Be the first to comment on this lesson.