Avatar ·

Как форматировать число с разделением тысяч запятыми в JavaScript?

Всем привет! Я новичок в JavaScript и столкнулся с такой проблемой: мне нужно выводить на странице большие числа, например, цену товара или количество просмотров. Но когда число большое, например 1234567, оно выглядит нечитаемо. Хочется, чтобы оно отображалось как "1,234,567" — с запятыми между разрядами тысяч. Я пробовал написать свою функцию, но она работает криво: ```javascript function formatNumber(num) { let str = num.toString(); let result = ''; for (let i = 0; i < str.length; i++) { if (i > 0 && i % 3 === 0) { result = ',' + result; } result = str[str.length - 1 - i] + result; } return result; } console.log(formatNumber(1234567)); // Выводит "1,234,567" — вроде работает, но если число 123456, то получается "123,456" — а нужно "123,456". ``` Но я заметил, что если число отрицательное или с десятичной частью (например, -1234567.89), то всё ломается. Плюс, мне кажется, что мой код слишком громоздкий. Может, есть встроенный метод в JavaScript для этого? Или какой-то простой и надёжный способ? Подскажите, пожалуйста, как правильно решить эту задачу, чтобы работало для любых чисел: целых, дробных, отрицательных. Заранее спасибо! <<>>

Лучший способ: использовать toLocaleString()

Самый простой и надёжный способ форматирования чисел с разделением тысяч — это встроенный метод Number.prototype.toLocaleString(). Он не только добавляет запятые, но и корректно обрабатывает отрицательные числа, десятичные дроби, а также учитывает локальные настройки (например, в некоторых странах используют точки или пробелы).

const number = 1234567.89;
console.log(number.toLocaleString()); // "1,234,567.89" (для локали en-US)

// Для отрицательных чисел:
const negative = -1234567.89;
console.log(negative.toLocaleString()); // "-1,234,567.89"

// Если нужно гарантировать американский формат (запятые и точки):
console.log(number.toLocaleString('en-US')); // "1,234,567.89"

// Для целых чисел:
const integer = 1234567;
console.log(integer.toLocaleString('en-US')); // "1,234,567"

Как это работает?

Метод toLocaleString() принимает два необязательных аргумента:

  • locale (строка) — код языка и региона, например 'en-US' (английский, США), 'de-DE' (немецкий, Германия — там используют точки как разделители тысяч и запятые для дробной части).
  • options (объект) — дополнительные настройки форматирования, такие как minimumFractionDigits, maximumFractionDigits, style (для валюты или процентов) и другие.

Пример с настройками:

const price = 1234567.8912;
console.log(price.toLocaleString('en-US', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
}));
// "1,234,567.89" — округлено до двух знаков после запятой

Если нужно только разделение тысяч (без локализации)

Если вы хотите гарантированно использовать запятые в качестве разделителя тысяч и точку для десятичной части, независимо от локали пользователя, можно создать простую функцию:

function formatWithCommas(x) {
    // Разделяем целую и дробную части
    const parts = x.toString().split('.');
    // Форматируем целую часть с помощью регулярного выражения
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    return parts.join('.');
}

console.log(formatWithCommas(1234567.89)); // "1,234,567.89"
console.log(formatWithCommas(-1234567));   // "-1,234,567"
console.log(formatWithCommas(123456));     // "123,456"

Объяснение регулярного выражения

  • \B — соответствует позиции, где нет границы слова (т.е. внутри числа).
  • (?=(\d{3})+(?!\d)) — положительный просмотр вперёд: проверяет, что за текущей позицией следует одна или более групп из трёх цифр, после которых нет цифры.
  • Этот метод не затрагивает дробную часть и правильно обрабатывает отрицательные числа, так как минус не является цифрой.

Почему ваш код не работал?

Ваш код пытался вставлять запятые с конца, но логика с i % 3 === 0 неверна: вы начинали отсчёт с первой цифры слева, а нужно с конца. Кроме того, он не обрабатывал десятичные числа и отрицательные значения. Используйте готовые решения — они проверены временем.

Рекомендация: для большинства проектов используйте toLocaleString() — он встроен в JavaScript, поддерживается во всех современных браузерах и Node.js, и автоматически адаптируется под регион пользователя. Если нужен строгий формат (всегда запятые), используйте регулярное выражение.

<<>>

Альтернативный подход: Intl.NumberFormat

Если вам нужно больше контроля над форматированием, используйте объект Intl.NumberFormat. Он является более производительным, чем toLocaleString(), если вы форматируете много чисел, так как его можно создать один раз и переиспользовать.

const formatter = new Intl.NumberFormat('en-US', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
});

console.log(formatter.format(1234567.891)); // "1,234,567.89"
console.log(formatter.format(-9876543.21)); // "-9,876,543.21"
console.log(formatter.format(1000));        // "1,000.00"

Для форматирования валюты

С помощью Intl.NumberFormat легко добавить символ валюты:

const currencyFormatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 2
});
console.log(currencyFormatter.format(1234567.89)); // "$1,234,567.89"

Когда это полезно?

  • Если вы форматируете числа в цикле (например, выводите список цен), создайте объект Intl.NumberFormat один раз вне цикла — это ускорит выполнение.
  • Если нужно поддерживать разные локали динамически, можно менять locale при создании экземпляра.
  • Этот метод также корректно работает с отрицательными числами и дробями.

Оба подхода (toLocaleString и Intl.NumberFormat) являются стандартными и рекомендуемыми. Выбирайте тот, который удобнее в вашем контексте.