Formatting numbers to make them more readable is an important part of many applications. By adding commas to numbers with many digits, large numbers become easier to read at a glance.
In JavaScript, there are a few different methods you can use to add commas to numbers. In this comprehensive guide, we‘ll explore the various ways to format numbers with commas in JavaScript.
Using the toLocaleString() Method
The easiest way to add commas to a number in JavaScript is with the toLocaleString() method. This is a built-in method that all numbers have access to.
Here‘s an example:
let num = 12345679;
let formattedNum = num.toLocaleString();
console.log(formattedNum); // 12,345,679
The toLocaleString() method converts the number to a string, formatted according to the locale rules. By default it will use the user‘s locale setting in their browser.
You can also pass in a locale as a parameter:
let num = 12345679;
let formattedNum = num.toLocaleString("en-US");
console.log(formattedNum); // 12,345,679
Some common locales are:
en-US– English (United States)en-GB– English (United Kingdom)de-DE– Germanfr-FR– Frenchja-JP– Japanese
The locale determines the delimiter used between number groups (typically commas or spaces).
One caveat with toLocaleString() is that it will not work on BigInt values. So make sure to convert a BigInt to a regular number first:
let bigNum = 1234567890123456789n;
let formattedBigNum = Number(bigNum).toLocaleString();
console.log(formattedBigNum); // 123,456,789,012,345,678,912
Formatting Numbers with Intl.NumberFormat
The Intl object in JavaScript contains functionality for internationalization of numbers, dates, and more.
We can use Intl.NumberFormat to format numbers with commas:
let num = 12345679;
let formattedNum = new Intl.NumberFormat("en-US").format(num);
console.log(formattedNum); // 12,345,679
Intl.NumberFormat gives us more flexibility and options than toLocaleString().
We configure the formatting by passing in an options object as the second parameter:
let options = {
style: "currency",
currency: "USD"
};
let formattedNum = new Intl.NumberFormat("en-US", options).format(12345679);
console.log(formattedNum); // $12,345,679.00
Some available options include:
style–decimal,currency, orpercentcurrency– currency code like"USD"minimumFractionDigits/maximumFractionDigits– number of decimal placesuseGrouping– whether to group with commas or not
Review the MDN documentation on Intl.NumberFormat for all available options.
The main advantage over toLocaleString() is having fine-grained control with the options parameter.
Adding Commas with Regular Expressions
We can also use regular expressions to insert commas into numbers in JavaScript.
Here‘s a regex that will find all digits that should be followed by a comma:
const formattedNum = num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
Let‘s break this down:
- First, convert the number to a string using
toString() \Bmatches positions where there should NOT be a word boundary(?=(\d{3})+(?!\d))is a positive lookahead that matches every 3 digits that are not followed by another digit- The
gflag performs a global search - We replace the matched positions with a comma
For example:
let num = 1234567890;
const formattedNum = num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
console.log(formattedNum); // 1,234,567,890
The regular expression method gives you complete control over the formatted output.
You can tweak the regexp to change which positions the commas are inserted at. But it can be more complex to understand compared to the previous methods.
Building a Reusable Format Number Function
For better reusability, we can wrap any of the above solutions into a custom format number function:
function formatNumber(num) {
return new Intl.NumberFormat("en-US").format(num);
}
let formattedNum = formatNumber(12345679);
console.log(formattedNum); // 12,345,679
Now we easily format any number by calling our formatNumber() function.
We can customize it by accepting options:
function formatNumber(num, locale = "en-US", style) {
const options = { style };
return new Intl.NumberFormat(locale, options).format(num);
}
let formattedNum = formatNumber(12345679, "de-DE", "currency");
console.log(formattedNum); // 12.345.679,00 €
Wrapping the formatting logic into a reusable function keeps our code DRY. This prevents duplicating the same formatting code everywhere.
And it‘s easy to change the implementation details later, without affecting all call sites. For example, we could swap out Intl.NumberFormat for a different solution in the future if needed.
Formatting Numbers in Templates
When including numbers inside string templates or DOM elements, we may also want them automatically formatted.
For example:
let price = 12345679;
let html = `
<div>
Price: ${price}
</div>
`;
We could call our formatNumber() function in the template:
let html = `
<div>
Price: ${formatNumber(price)}
</div>
`;
But this disrupts the readability of the template.
Another approach is to format it inline using toLocaleString():
let html = `
<div>
Price: ${price.toLocaleString()}
</div>
`;
This keeps everything inside the template clean and readable.
So in general, prefer using toLocaleString() directly inside templates if you need to format a number on-the-fly.
Formatting Decimals with Variable Precision
When working with decimal numbers, we may want to dynamically configure how many digits to display after the decimal point.
For example, limiting a number to 2 decimal places, or showing the full precision.
Here‘s how to format decimals with variable precision using Intl.NumberFormat:
function formatDecimal(num, digits) {
return new Intl.NumberFormat("en-US", {
minimumFractionDigits: digits,
maximumFractionDigits: digits
}).format(num);
}
let num = 123.456789;
console.log(formatDecimal(num, 2)); // 123.46
console.log(formatDecimal(num, 5)); // 123.45679
By tuning the minimumFractionDigits and maximumFractionDigits options, we control the decimal precision.
This allows cleanly displaying decimal numbers aligned for visual comparison, without messy long trailing digits:
| Item | Price |
|------------|-----------|
| Shoes | $39.99 |
| Backpack | $79.50 |
| Jacket | $199.00 |
Or showing the full precision when necessary:
| Measurement | Value |
|-------------|----------------|
| Length | 12.5379inches |
| Width | 5.28492 cm |
This degree of flexibility over decimal formatting helps present numeric data in a precise and readable format.
Adding Commas to Currency Values
When dealing with monetary values, we need to format the numbers appropriately as currency.
Here is how to add comma separators with currency symbols using Intl.NumberFormat:
function formatCurrency(amount) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
}).format(amount);
}
let price = 12345679;
console.log(formatCurrency(price)); // $12,345,679.00
This handles both the comma separators as well as properly positioning the currency symbol and decimal points per locale rules.
We can customize the currency code using the currency option:
formatCurrency(price, "EUR"); // €12.345.679,00
formatCurrency(price, "JPY"); // ¥12,345,679
formatCurrency(price, "BDT"); // ৳ 12,34,56,79.00
And currency formatting works well with variable decimal precision:
function formatCurrency(amount, digits = 2) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: digits,
maximumFractionDigits: digits
}).format(amount);
}
formatCurrency(123.456, 2); // $123.46
formatCurrency(123.456, 4); // $123.4560
Properly formatted currencies improve the professionalism of applications dealing with monetary data.
Localized Number Formatting
For international web applications, number formatting should adapt to the user‘s locale preferences.
Let‘s build a formatNumber() function that takes the locale as a parameter:
function formatNumber(num, locale) {
return new Intl.NumberFormat(locale).format(num);
}
Now we can format numbers formatted correctly for a given locale:
// German formatting
formatNumber(12345679, "de-DE"); // 12.345.679
// Arabic digits
formatNumber(12345679, "ar-EG"); // ١٢٬٣٤٥٬٦٧٩
We could auto-detect the visitor‘s locale to provide localized formatting out-of-box:
// Get browser navigator language
const locale = navigator.language;
formatNumber(12345679, locale);
Or allow users to manually select their preferred locale via a settings drop-down.
This helps format numbers in a familiar, readable way matching user expectations across the world.
One challenge with localizing number formatting is sorting formatted numbers textually may produce counter-intuitive ordering:
12.345.679 (de-DE)
1,234,567 (es-ES)
١٢،٣٤٥،٦٧٩ (ar-EG)
Therefore it‘s important to format numbers after sorting for a consistent user experience:
let numbers = [12, 34, 1000, 5];
// Sort numbers
numbers.sort((a, b) => a - b);
// Format localized
numbers.map(num => formatNumber(num, locale));
This avoids confusion from locale-specific idiosyncrasies interfering with logical numeric sorting.
Optimized Formatting for Large Datasets
When formatting large numeric datasets, converting every single number can harm performance due to the sheer quantity.
Let‘s explore efficient approaches to optimize this formatting work.
For example, formatting an array of 10,000 numbers with Intl.NumberFormat:
let largeDataset = [];
for (let i = 0; i < 10000; i++) {
largeDataset.push(i + 1);
}
let start = performance.now();
largeDataset.forEach(num => {
Intl.NumberFormat("en-US").format(num);
});
let duration = performance.now() - start;
console.log(`Took ${duration} ms to format 10,000 numbers`);
// Took 88.20000004768372 ms to format 10,000 numbers
This performs reasonably fast, but we‘re still doing extra work reformatting the Intl formatter instance 10,000 separate times.
We can optimize by caching the formatter:
let formatter = new Intl.NumberFormat("en-US");
let start = performance.now();
largeDataset.forEach(num => {
formatter.format(num);
});
let duration = performance.now() - start;
console.log(`Took ${duration} ms with cached formatter`);
// Took 14.09999942779541 ms with cached formatter
Now that‘s a 6x speedup! By reusing the formatter, we save substantial time not having to rebuild it continually.
Alternative options like toLocaleString() or regexp are faster still for large arrays:
// toLocaleString()
start = performance.now();
largeDataset.forEach(num => {
num.toLocaleString();
});
console.log(`toLocaleString took ${performance.now() - start} ms`);
// toLocaleString took 20.700000286102295 ms
// Regular expression
start = performance.now();
largeDataset.forEach(num => {
num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
});
console.log(`RegExp took ${performance.now() - start} ms`);
// RegExp took 15.199999809265137 ms
So in situations like data dashboards, avoid premature optimization until formatting becomes a measurable bottleneck. But this shows techniques available to speed upCOMMON large-scale number formatting workloads when needed.
Summary
We explored several practical techniques for formatting numbers with commas in JavaScript:
- toLocaleString() – Simple locale-aware formatting
- Intl.NumberFormat – Flexible formatting options via configuration
- Regular expressions – Powerful regex-based comma insertion
- Reusable functions – Encapsulate formatting logic for easy reuse
- Template formatting – Inline formatting inside string templates
- Decimal precision – Control decimal points with min/max digits
- Currency formatting – Proper comma handling for money values
- Localization – Format numbers to match user locale preferences
- Optimization – Caching and algorithmic improvements for large datasets
Learning how to properly format numbers is an indispensable skill across both client and server-side JavaScript. This guide explored a variety formats numbers in code, along with techniques to implement performant large-scale formatting.
I hope these real-world examples give provide a deeper insight into working with numeric data in JavaScript. Let me know if you have any other numeric formatting use cases you‘d like to see covered!


