How to output numbers with leading zeros in JavaScript?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Leading zeros in JavaScript are a string formatting operation, not a numeric one. JavaScript numbers do not store or display leading zeros, so the approach is always to convert to a string and pad it to the desired width. The modern solution is String(value).padStart(width, "0"), which is built into every current JavaScript engine and covers the vast majority of use cases cleanly.
padStart: The Standard Approach
String.prototype.padStart() was introduced in ES2017 and is the canonical way to add leading zeros:
The method takes two arguments: the target length and the padding character. If the string is already at or beyond the target length, padStart returns it unchanged:
This is important: padStart never truncates. If the number has more digits than the target width, it comes through unmodified.
Writing a Reusable Helper
When the same formatting rule appears in multiple places, wrap it in a function:
This keeps the intent clear and avoids scattering padStart calls with magic numbers throughout the codebase.
Formatting Dates and Times
The most common real-world use case for leading zeros is date and time formatting. Hours, minutes, seconds, months, and days are conventionally displayed as two-digit values:
This replaces the older pattern of writing if (value < 10) return "0" + value scattered across every formatting call.
Formatting File Names and IDs
Sequential file names and identifiers often require fixed-width numbering for correct alphabetical sorting:
Without leading zeros, file explorers sort frame_10.png before frame_2.png because string comparison works character by character.
Handling Negative Numbers
A straightforward padStart on a negative number places zeros before the minus sign, which is almost never the desired result:
Handle the sign separately:
Note that the width parameter here refers to the digit width, not including the sign. Adjust if your use case requires a fixed total width including the sign character.
Legacy Approach: Concatenate and Slice
Before padStart existed, the standard workaround was to prepend zeros and slice from the end:
This works but is harder to read at a glance. It also has a subtle bug with negative numbers and values longer than width. Use padStart in any codebase that targets ES2017 or later, which includes all current browsers and Node.js versions from 8 onward.
Using Intl.NumberFormat for Locale-Aware Formatting
For more complex numeric formatting, the Intl.NumberFormat API provides built-in support for minimum integer digits:
Setting useGrouping: false prevents the formatter from inserting commas or other grouping separators. This approach is useful when you are already using Intl for currency or percentage formatting and want consistent number presentation.
TypeScript Type Safety
In TypeScript projects, you may want to distinguish between raw numbers and formatted strings at the type level:
This is a lightweight branding pattern that prevents mixing padded and unpadded values.
Comparison of Methods
| Method | Browser support | Handles negatives | Truncates | Readability |
padStart | ES2017+ (all modern) | Needs manual handling | No | High |
| Concatenate + slice | All versions | Breaks silently | Yes (can clip digits) | Medium |
Intl.NumberFormat | All modern | Built-in | No | High |
Custom if checks | All versions | Manual | No | Low |
Common Pitfalls
- Expecting JavaScript numbers to store leading zeros.
007as a number literal is7. Leading zeros are purely a string presentation concern. - Padding a negative number without separating the sign.
String(-7).padStart(4, "0")produces"0-7", not"-007". - Converting a padded string back to a number.
Number("00042")returns42, stripping the leading zeros. Keep padded values as strings through their entire lifecycle. - Using a fixed width that the data will eventually outgrow. If you pad invoice numbers to 4 digits, the 10,000th invoice breaks the format. Choose a width with growth margin.
- Using the legacy slice approach in modern codebases. It is harder to read, harder to maintain, and has edge-case bugs that
padStartavoids.
Summary
- Leading zeros in JavaScript are created by converting numbers to strings and padding them. Numbers themselves cannot hold leading zeros.
String(value).padStart(width, "0")is the standard modern solution, available in ES2017 and all current runtimes.- Handle negative numbers by separating the sign before padding the absolute value.
Intl.NumberFormatwithminimumIntegerDigitsprovides an alternative when locale-aware formatting is already in use.- Always keep padded values as strings. Converting back to a number discards the padding.
Related reading
- How to overlay one div over another div
- How to parse JSON using Node.js?
- How to pass props to {this.props.children}
- How to perform an async task against es6 generators in loop
- How to perform an integer division, and separately get the remainder, in JavaScript
- How to perform multiple asynchronous requests starting one after another
- How to pick an event listener that will let me wait until async.times is finished to run a function
- How to populate select options from an Api call in React js on page load
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.