Number.prototype.toString()
Without an argument it is the ordinary conversion every template literal performs. With a radix it becomes the shortest way to produce hex, binary or any base up to 36.
Demo
Digits above 9 are written as lowercase letters, so base 16 gives 'ff' and base 36 uses the whole alphabet — which is why base 36 is a popular way to shorten numeric ids. Negative numbers get a minus sign rather than a two's-complement representation, so (-255).toString(2) is '-11111111' and not a bit pattern. The inverse is parseInt with the same radix.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| radix | number | no (10) | The base, 2 to 36. Digits above 9 use lowercase letters. Anything outside the range throws RangeError. |
Return value
string — The number written in the given base. Default base 10, which is also what implicit string coercion produces.
Common patterns
const hex = n => n.toString(16).padStart(2, '0');
Math.random().toString(36).slice(2, 10);
parseInt(n.toString(16), 16) === n;
Examples
Pitfalls
255.toString(16)
(255).toString(16)
(-255).toString(2)
(-255 >>> 0).toString(2)
(0.1).toString(3)
(Math.round(0.1 * 1000)).toString(3)
(5).toString(16)
(5).toString(16).padStart(2, '0')
When to use
- Producing hex, binary or octal representations
- Compact ids via base 36
- Debugging bit patterns, with an unsigned shift first
- Explicit conversion where a template literal would be unclear
- Formatting for a user → toLocaleString or Intl.NumberFormat
- A fixed number of decimals → toFixed
- Bit patterns of negatives → shift to unsigned first
- Ordinary coercion → a template literal is shorter
Notes
FAQ
Because the parser treats the dot as a decimal point and then finds a method name where it expected digits. Parentheses around the number fix it, and so does a second dot — 255..toString(16) works because the first dot completes the numeric literal.
(255).toString(16); // fine 255..toString(16); // also fine 255 .toString(16); // fine too, with a space