I used the idea from Kerry's answer, but I simplified it since I was just looking for something simple for my specific purpose. Here is what I have:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,        "0");
failures += !test(100,      "100");
failures += !test(1000,     "1,000");
failures += !test(10000,    "10,000");
failures += !test(100000,   "100,000");
failures += !test(1000000,  "1,000,000");
failures += !test(10000000, "10,000,000");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}


The regex uses two lookahead assertions:

  • a positive one to look for any point in the string that has a multiple of 3 digits in a row after it,
  • a negative assertion to make sure that point only has exactly a multiple of 3 digits. The replacement expression puts a comma there.

For example, if you pass it 123456789.01, the positive assertion will match every spot to the left of the 7 (since 789 is a multiple of 3 digits, 678 is a multiple of 3 digits, 567, etc.).

The negative assertion checks that the multiple of 3 digits does not have any digits after it. 789 has a period after it so it is exactly a multiple of 3 digits, so a comma goes there. 678 is a multiple of 3 digits, but it has a 9 after it, so those 3 digits are part of a group of 4, and a comma does not go there. Similarly for 567.

456789 is 6 digits, which is a multiple of 3, so a comma goes before that. 345678 is a multiple of 3, but it has a 9 after it, so no comma goes there. And so on. The \B keeps the regex from putting a comma at the beginning of the string.

neu-rah mentioned that this function adds commas in undesirable places if there are more than 3 digits after the decimal point. If this is a problem, you can use this function:

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0              , "0");
failures += !test(0.123456       , "0.123456");
failures += !test(100            , "100");
failures += !test(100.123456     , "100.123456");
failures += !test(1000           , "1,000");
failures += !test(1000.123456    , "1,000.123456");
failures += !test(10000          , "10,000");
failures += !test(10000.123456   , "10,000.123456");
failures += !test(100000         , "100,000");
failures += !test(100000.123456  , "100,000.123456");
failures += !test(1000000        , "1,000,000");
failures += !test(1000000.123456 , "1,000,000.123456");
failures += !test(10000000       , "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

T.J. Crowder pointed out that now that JavaScript has lookbehind (support info), it can be solved in the regular expression itself:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,               "0");
failures += !test(0.123456,        "0.123456");
failures += !test(100,             "100");
failures += !test(100.123456,      "100.123456");
failures += !test(1000,            "1,000");
failures += !test(1000.123456,     "1,000.123456");
failures += !test(10000,           "10,000");
failures += !test(10000.123456,    "10,000.123456");
failures += !test(100000,          "100,000");
failures += !test(100000.123456,   "100,000.123456");
failures += !test(1000000,         "1,000,000");
failures += !test(1000000.123456,  "1,000,000.123456");
failures += !test(10000000,        "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

(?<!\.\d*) is a negative lookbehind that says the match can't be preceded by a . followed by zero or more digits. The negative lookbehind is faster than the split and join solution (comparison), at least in V8.

Answer from Elias Zamaria on Stack Overflow
Top answer
1 of 16
3954

I used the idea from Kerry's answer, but I simplified it since I was just looking for something simple for my specific purpose. Here is what I have:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,        "0");
failures += !test(100,      "100");
failures += !test(1000,     "1,000");
failures += !test(10000,    "10,000");
failures += !test(100000,   "100,000");
failures += !test(1000000,  "1,000,000");
failures += !test(10000000, "10,000,000");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}


The regex uses two lookahead assertions:

  • a positive one to look for any point in the string that has a multiple of 3 digits in a row after it,
  • a negative assertion to make sure that point only has exactly a multiple of 3 digits. The replacement expression puts a comma there.

For example, if you pass it 123456789.01, the positive assertion will match every spot to the left of the 7 (since 789 is a multiple of 3 digits, 678 is a multiple of 3 digits, 567, etc.).

The negative assertion checks that the multiple of 3 digits does not have any digits after it. 789 has a period after it so it is exactly a multiple of 3 digits, so a comma goes there. 678 is a multiple of 3 digits, but it has a 9 after it, so those 3 digits are part of a group of 4, and a comma does not go there. Similarly for 567.

456789 is 6 digits, which is a multiple of 3, so a comma goes before that. 345678 is a multiple of 3, but it has a 9 after it, so no comma goes there. And so on. The \B keeps the regex from putting a comma at the beginning of the string.

neu-rah mentioned that this function adds commas in undesirable places if there are more than 3 digits after the decimal point. If this is a problem, you can use this function:

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0              , "0");
failures += !test(0.123456       , "0.123456");
failures += !test(100            , "100");
failures += !test(100.123456     , "100.123456");
failures += !test(1000           , "1,000");
failures += !test(1000.123456    , "1,000.123456");
failures += !test(10000          , "10,000");
failures += !test(10000.123456   , "10,000.123456");
failures += !test(100000         , "100,000");
failures += !test(100000.123456  , "100,000.123456");
failures += !test(1000000        , "1,000,000");
failures += !test(1000000.123456 , "1,000,000.123456");
failures += !test(10000000       , "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

T.J. Crowder pointed out that now that JavaScript has lookbehind (support info), it can be solved in the regular expression itself:

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

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

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} {result}`);
    return pass;
}

let failures = 0;
failures += !test(0,               "0");
failures += !test(0.123456,        "0.123456");
failures += !test(100,             "100");
failures += !test(100.123456,      "100.123456");
failures += !test(1000,            "1,000");
failures += !test(1000.123456,     "1,000.123456");
failures += !test(10000,           "10,000");
failures += !test(10000.123456,    "10,000.123456");
failures += !test(100000,          "100,000");
failures += !test(100000.123456,   "100,000.123456");
failures += !test(1000000,         "1,000,000");
failures += !test(1000000.123456,  "1,000,000.123456");
failures += !test(10000000,        "10,000,000");
failures += !test(10000000.123456, "10,000,000.123456");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
.as-console-wrapper {
    max-height: 100% !important;
}

(?<!\.\d*) is a negative lookbehind that says the match can't be preceded by a . followed by zero or more digits. The negative lookbehind is faster than the split and join solution (comparison), at least in V8.

2 of 16
3275

I'm surprised nobody mentioned Number.prototype.toLocaleString. It's implemented in JavaScript 1.5 (which was introduced in 1999), so it's basically supported across all major browsers.

var n = 34523453.345;
console.log(n.toLocaleString());    // "34,523,453.345"

It also works in Node.js as of v0.12 via inclusion of Intl.

If you want something different, Numeral.js might be interesting.

Discussions

Formatting a number with commas as a thousand digits without converting it into a string
I’ve tried this but when I checked it with console.log(isNaN(conversion));, it returns true. How do you format this without it converting into a string? const income = Number(8000); const conversion = income.toLocaleString(navigator.language, { minimumFractionDigits: 2 }); console.log(is... More on forum.freecodecamp.org
🌐 forum.freecodecamp.org
1
1
March 7, 2022
Format a Number with Commas in React
This is just vanilla JS, no? More on reddit.com
🌐 r/react
4
0
March 22, 2023
Space instead of Comma in NumberFormat
Hello, is there a way to have this format but with space instead of comma? (It is in the column definition on table) None of these works I know I can manually type the format there but it doesnt work the way I expected. Am I missing something? The only way I was able to walk around it is by ... More on forum.inductiveautomation.com
🌐 forum.inductiveautomation.com
0
February 14, 2024
How to Display Numbers with a Comma Separator
Hey Guys, Struggling with understanding how to get my code to display commas. While I know its been attempted to be answered before my situation is a bit unique I think. In my my database I have both text and numbers (different columns). The numbers are inputted as 0000.00, but displayed with ... More on forum.wixstudio.com
🌐 forum.wixstudio.com
0
September 26, 2019
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Intl › NumberFormat
Intl.NumberFormat - JavaScript | MDN
In order to get the format of the language used in the user interface of your application, make sure to specify that language (and possibly some fallback languages) using the locales argument: ... const number = 123456.789; // German uses comma as decimal separator and period for thousands console.log(new Intl.NumberFormat("de-DE").format(number)); // 123.456,789 // Arabic in most Arabic speaking countries uses real Arabic digits console.log(new Intl.NumberFormat("ar-EG").format(number)); // ١٢٣٤٥٦٫٧٨٩ // India uses thousands/lakh/crore separators console.log(new Intl.NumberFormat("en-IN").format(number)); // 1,23,456.789 // the nu extension key requests a numbering system, e.g.
🌐
Favtutor
favtutor.com › articles › format-numbers-commas-javascript
Format Numbers with Commas in JavaScript (with code)
February 5, 2024 - JavaScript offers several methods for formatting numbers with commas. Here we will cover the toLocaleString() method, leveraging the Intl.NumberFormat() object, and using regular expressions.
🌐
DEV Community
dev.to › lavary › add-commas-to-numbers-in-javascript-explained-with-examples-27k8
Add commas to numbers in JavaScript (Explained with examples) - DEV Community
February 6, 2023 - This regular expression starts with a boundary (\B) to avoid a comma at the beginning of the number. Then, it uses to lookaheads to mark numbers in hundreds. Consequently, The replace() method places a comma in each match. Formatting numbers can be done in a variety of ways in JavaScript.
🌐
Reddit
reddit.com › r/react › format a number with commas in react
r/react on Reddit: Format a Number with Commas in React
March 22, 2023 -

If you’re working with large numbers in React, formatting them with commas for readability is often helpful. Fortunately, there’s a simple way to do this using the built-in Intl.NumberFormat and toLocaleString() method.

import React from "react";  
export default function App() {  
    const num = 123456.789;  
    const options = {  maximumFractionDigits: 2   }   
    const formattedNumber = Intl.NumberFormat("en-US",options).format(num); 
  
    return <h2>{formattedNumber}</h2>; 
}  
//Output => 123,456.78

To learn more about the Intl.NumberFormat and toLocaleString() methods, visit 👉 : Format a Number with Commas in React

Find elsewhere
🌐
Stack Abuse
stackabuse.com › bytes › format-numbers-with-commas-in-javascript
Format Numbers with Commas in JavaScript
August 7, 2023 - This method automatically formats the number according to the user's locale, making it an excellent choice for internationalization. For my locale, it uses commas after every third digit. Note: We're used to seeing numbers, like the one shown above, presented with only two digits after the decimal when displayed as currency.
🌐
Medium
medium.com › @noffybarudwale › javascript-format-numbers-with-commas-and-decimals-86b68ec5b180
JavaScript : Format numbers with commas and decimals. | by Nofij Barudwale | Medium
October 13, 2021 - The NumberFormat() object is used to represent numbers in a language-sensitive formatting. It can be used to represent currency or percentages according to the locale specified. The locales parameter of this object is used to specify the format ...
🌐
GeeksforGeeks
geeksforgeeks.org › javascript › how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
How to print a number with commas as thousands separators in JavaScript? - GeeksforGeeks
July 12, 2025 - The format() method of this object can be used to return a string of the number in the specified locale and formatting options. This will format the number with commas at the thousands of places and return a string with the formatted number.
🌐
Inductive Automation
forum.inductiveautomation.com › ignition
Space instead of Comma in NumberFormat - Ignition - Inductive Automation Forum
February 14, 2024 - Hello, is there a way to have this format but with space instead of comma? (It is in the column definition on table) None of these works I know I can manually type the format there but it doesnt work the way I expected. Am I missing something? The only way I was able to walk around it is by ...
🌐
DEV Community
dev.to › onlinemsr › big-numbers-no-worries-javascript-format-number-with-commas-n6j
Big Numbers, No Worries: JavaScript Format Number With Commas - DEV Community
March 23, 2024 - If you are a web developer, you ... number, like 1000000 or 1,000,000, for better readability. Using the toLocaleString() method you can format numbers with commas....
🌐
Wix Studio
forum.wixstudio.com › ask the community
How to Display Numbers with a Comma Separator - Ask the community - Community Support Forum | Wix Studio
September 26, 2019 - Hey Guys, Struggling with understanding how to get my code to display commas. While I know its been attempted to be answered before my situation is a bit unique I think. In my my database I have both text and numbers (different columns). The numbers are inputted as 0000.00, but displayed with ...
🌐
Crio
crio.do › blog › format-numbers-with-commas-as-thousands-separators-2025-javascript-criodo
How to Format a Number with Commas as Thousands Separators?
December 26, 2024 - Formatting numbers with commas as thousands separators is essential for enhancing readability, especially when displaying large numbers in user interfaces. This is a common requirement for financial data, statistics, and other applications. Here’s a concise and effective way to format numbers using JavaScript...
🌐
TypeOfNaN
typeofnan.dev › how-to-add-thousandths-place-comma-every-three-digits-in-javascript
How to Add a Thousandths Place Comma (Every Three Digits) in JavaScript | TypeOfNaN
December 29, 2020 - If our input is a number, we’ll want to make sure to covert it to a string before applying the regex. function addCommas(num) { return num.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,'); } addCommas(1000); // 1,000 addCommas(1000000); // 1,000,000 addCommas(100); // 1000 · And that’s it! A couple fairly straightforward ways to add commas to your large numbers.
🌐
HubSpot
community.hubspot.com › t5 › CMS-Development › 3-digit-delimited-comma › m-p › 779264
Solved: HubSpot Community - 3-digit delimited comma - HubSpot Community
April 7, 2023 - const number = 1234567.89; const formattedNumber = number.toLocaleString('en-US'); // "1,234,567.89" In this example, 'en-US' specifies the locale as English (United States). If you want to use a different character as the delimiter, you can specify it as an option: const number = 1234567.89; const options = { useGrouping: true, minimumFractionDigits: 2, maximumFractionDigits: 2, minimumIntegerDigits: 1, style: 'currency', currency: 'USD', currencyDisplay: 'symbol', numberingSystem: 'latn', // use latin digits notation: 'compact', compactDisplay: 'short', signDisplay: 'auto' }; const formattedNumber = number.toLocaleString('en-US', options); // "$1.2M"
🌐
Coda
community.coda.io › t › decimal-comma-instead-of-point › 43029
Decimal Comma instead of point - Coda Maker Community
September 23, 2023 - Years ago, I asked Coda for an option to use a comma instead of a dot in numbers. Large parts of the word write numbers like so: 1.000,00 It is still not implemented, right? Or am I overlooking something? I mean, reall…
🌐
Retool
community.retool.com › 💬 feature requests
Comma as number separator - 💬 Feature Requests - Retool Forum
August 24, 2023 - A request to be able to change the decimal separator to a comma and thousands separator to a dot. This should be set per organisation or should follow the browser localization settings. In Europe (and a lot of other cou…