Форматирование чисел в валюту в JavaScript: 3 лучших способа

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Деньги любят порядок: как превратить число в красивую цену на JavaScript?

Представьте: вы пишете интернет-магазин. Сервер отдаёт цену товара — просто число 1999.5. Показывать пользователю «сырое» число — моветон. Клиент хочет видеть "$1,999.50" или, если вы в России, "1 999,50 ₽".

Этот вопрос мучает тысячи разработчиков на Stack Overflow. Сегодня мы раз и навсегда разберёмся, как правильно форматировать числа в валютные строки в JavaScript. Вы узнаете про встроенные методы, их особенности и когда какой способ лучше использовать.

Почему просто .toFixed(2) — это плохая идея?

Многие новички делают так:

const price = 1999.5;
console.log('$' + price.toFixed(2)); // "$1999.50"

Вроде бы работает. Но это — бомба замедленного действия. Почему?

  • Нет разделителей разрядов. $1999.50 читается хуже, чем $1,999.50.
  • Нет локализации. В Европе запятая — десятичный разделитель, точка — разделитель тысяч. Ваш код сломается.
  • Жёстко зашит символ валюты. Поменять $ на € — значит лезть в код.

К счастью, современный JavaScript предоставляет нам элегантные инструменты. Давайте изучим их.

Способ №1: Intl.NumberFormat — король форматирования (рекомендуется)

Этот объект — часть Internationalization API. Он создан специально для работы с локалью, валютами и числами. Это самый правильный и гибкий способ.

Базовый пример

const formatter = new Intl.NumberFormat('ru-RU', {
    style: 'currency',
    currency: 'RUB'
});

console.log(formatter.format(1999.5)); // "1 999,50 ₽"

Всё! JavaScript сам расставил пробелы, запятые и добавил символ рубля. Магия, да?

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

Конструктор принимает два аргумента:

  • locales — строка с кодом локали (например, 'en-US', 'de-DE', 'ru-RU').
  • options — объект настройки. Ключевое: style: 'currency' и currency: 'USD'.

Настройка под любую валюту

Хотите доллары для США?

const usFormatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
});
console.log(usFormatter.format(2500)); // "$2,500.00"

Евро для Германии?

const deFormatter = new Intl.NumberFormat('de-DE', {
    style: 'currency',
    currency: 'EUR'
});
console.log(deFormatter.format(2500)); // "2.500,00 €"

Обратите внимание: в Германии точка — разделитель тысяч, а запятая — десятичный знак. Intl всё делает за вас.

Дополнительные опции

Хотите убрать дробную часть (центов нет)?

const formatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 0,
    maximumFractionDigits: 0
});
console.log(formatter.format(1999.5)); // "$2,000" (округлило)

Нужно показывать всегда 4 знака после запятой? Пожалуйста:

const preciseFormatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 4
});
console.log(preciseFormatter.format(1.2)); // "$1.2000"

Плюсы: нативный, быстрый, поддерживает все валюты мира, легко меняет локаль.

Минусы: не работает в очень старых браузерах (IE 10 и ниже — но это уже история).

Способ №2: Number.prototype.toLocaleString() — быстрый и простой

Этот метод — "младший брат" Intl.NumberFormat. Он встроен прямо в прототип числа и делает то же самое, но с меньшим контролем.

Пример

const price = 2500.75;
console.log(price.toLocaleString('en-US', {
    style: 'currency',
    currency: 'USD'
})); // "$2,500.75"

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

Когда использовать toLocaleString?

  • Для разового форматирования.
  • В простых скриптах, где производительность не критична.
  • Когда лень писать лишнюю строку с new.

Плюсы: короткая запись, не нужно создавать отдельный объект.

Минусы: при массовом форматировании работает медленнее, чем Intl.NumberFormat.

Способ №3: Ручное форматирование — когда API не подходит

Бывают ситуации, когда встроенные методы не годятся. Например:

  • Вы форматируете криптовалюты (BTC, ETH) — у них нет стандартных кодов в Intl.
  • Вам нужен нестандартный формат, например, "USD 1 234.56" без знака валюты.
  • Вы поддерживаете очень старые браузеры (IE 9 и ниже).

Тогда пишем свою функцию. Вот элегантный вариант:

function formatCurrency(amount, currencySymbol = '$', decimalSeparator = '.', thousandsSeparator = ',') {
    // 1. Фиксируем 2 знака после запятой
    let parts = amount.toFixed(2).split('.');
    
    // 2. Добавляем разделители тысяч
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
    
    // 3. Собираем строку
    return currencySymbol + parts.join(decimalSeparator);
}

console.log(formatCurrency(1234567.89)); // "$1,234,567.89"
console.log(formatCurrency(1234567.89, '€', ',', ' ')); // "€1 234 567,89"

Разберём регулярку: \B(?=(\d{3})+(?!\d)) — это "магический" паттерн, который находит позиции между разрядами тысяч. Он

Блоги

Рекомендаций по книгам