NeuroAgent

JavaScript Number Formatting with Commas: Complete Guide

Learn the best methods to format numbers with commas as thousands separators in JavaScript. Discover built-in Intl methods, regex patterns, and performance-optimized solutions for integers and floating-point numbers.

Question

How to format numbers with commas as thousands separators in JavaScript?

I’m trying to format integers in JavaScript with commas as thousands separators. For example, I want to convert the number 1234567 to “1,234,567”. Here’s my current implementation:

javascript
function numberWithCommas(x) {
    x = x.toString();
    var pattern = /(-?\d+)(\d{3})/;
    while (pattern.test(x))
        x = x.replace(pattern, "$1,$2");
    return x;
}

console.log(numberWithCommas(1000))

Is there a simpler or more elegant way to achieve this? It would be beneficial if the solution works with floating-point numbers as well, but that’s not a requirement. The solution doesn’t need to be locale-specific for choosing between periods and commas.

NeuroAgent

JavaScript offers several built-in methods for formatting numbers with commas as thousands separators. The most modern and elegant approach is using Intl.NumberFormat or toLocaleString(), which provide native browser support without manual string manipulation. For integers like 1234567, you can simply use 1234567.toLocaleString() to get “1,234,567”.

Contents

Built-in Methods

Using toLocaleString()

The simplest and most elegant solution is using the built-in toLocaleString() method:

javascript
const number = 1234567;
const formatted = number.toLocaleString();
console.log(formatted); // "1,234,567"

This method automatically handles thousands separators and works with both integers and floating-point numbers:

javascript
console.log(1234567.89.toLocaleString()); // "1,234,567.89"
console.log(1000.toLocaleString());       // "1,000"

Using Intl.NumberFormat

For more control and better performance in loops, use Intl.NumberFormat:

javascript
const formatter = new Intl.NumberFormat();
const formatted = formatter.format(1234567);
console.log(formatted); // "1,234,567"

You can create a reusable formatter:

javascript
// Create a reusable formatter
const currencyFormatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
});

// Use it multiple times
console.log(currencyFormatter.format(1234567)); // "$1,234,567.00"

Regular Expression Approach

Your current implementation using regular expressions is functional but can be simplified:

javascript
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

console.log(numberWithCommas(1234567)); // "1,234,567"

This regex pattern \B(?=(\d{3})+(?!\d)) uses a positive lookahead to find positions that are:

  • \B - Not at a word boundary (ensures we don’t add commas at the start)
  • (?=(\d{3})+) - Followed by groups of exactly 3 digits
  • (?!\d) - Not followed by any more digits (ensures we don’t add trailing commas)

Manual String Manipulation

For environments without Intl support or when you need maximum control:

javascript
function formatNumberWithCommas(num) {
    const parts = num.toString().split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    return parts.join('.');
}

console.log(formatNumberWithCommas(1234567));      // "1,234,567"
console.log(formatNumberWithCommas(1234567.89));   // "1,234,567.89"

Comparison of Methods

Method Performance Browser Support Flexibility Code Complexity
toLocaleString() Good All modern browsers High Very simple
Intl.NumberFormat Excellent (cached) All modern browsers Very high Simple
Regular Expression Moderate All browsers Medium Moderate
Manual parsing Good All browsers Low Simple

Handling Floating-Point Numbers

All built-in methods automatically handle decimal points:

javascript
const number = 1234567.8912;

// Using toLocaleString
console.log(number.toLocaleString()); // "1,234,567.891"

// Using Intl.NumberFormat
const formatter = new Intl.NumberFormat('en-US', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 4
});
console.log(formatter.format(number)); // "1,234,567.8912"

For your specific needs, you can create a simple wrapper:

javascript
function formatNumber(num) {
    return num.toLocaleString();
}

// Works with both integers and floats
console.log(formatNumber(1234567));    // "1,234,567"
console.log(formatNumber(1234567.89)); // "1,234,567.89"

Browser Support and Alternatives

Modern Browsers (Chrome, Firefox, Safari, Edge)

All modern browsers fully support Intl.NumberFormat and toLocaleString() with excellent performance.

Legacy Browsers (Internet Explorer)

For older browsers, you can use a polyfill or fall back to your regex approach:

javascript
if (!window.Intl) {
    // Fallback for older browsers
    function formatNumber(num) {
        return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    }
} else {
    // Modern approach
    function formatNumber(num) {
        return num.toLocaleString();
    }
}

Library Solutions

For advanced formatting needs, consider libraries like:

Performance Considerations

For formatting large numbers of values, Intl.NumberFormat is most efficient when cached:

javascript
// Cache formatter for better performance in loops
const numberFormatter = new Intl.NumberFormat();

function formatManyNumbers(numbers) {
    return numbers.map(num => numberFormatter.format(num));
}

// Much faster than calling toLocaleString() each time
const largeArray = Array.from({length: 1000}, (_, i) => i * 1000 + 123);
const formatted = formatManyNumbers(largeArray);

Conclusion

For your use case, the simplest and most elegant solution is to use toLocaleString():

javascript
function numberWithCommas(x) {
    return x.toLocaleString();
}

console.log(numberWithCommas(1234567)); // "1,234,567"

Key takeaways:

  1. Built-in methods are preferred: toLocaleString() and Intl.NumberFormat are the most reliable and maintainable solutions
  2. Performance matters: For bulk operations, cache Intl.NumberFormat instances
  3. Compatibility: Modern browsers handle all these methods excellently
  4. Simplicity beats complexity: Your regex approach works but isn’t as clean as built-in solutions
  5. Flexibility: Built-in methods automatically handle both integers and floats

For most applications, toLocaleString() provides the perfect balance of simplicity and functionality. If you need more control over formatting options or are working with very large datasets, Intl.NumberFormat offers better performance and customization.

Sources

  1. MDN Web Docs - Intl.NumberFormat
  2. MDN Web Docs - Number.prototype.toLocaleString
  3. ECMAScript Internationalization API Specification
  4. Can I Use - Intl API