Avatar ·

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

Привет всем! Я пишу интернет-магазин на JavaScript и столкнулся с такой проблемой: при выводе цен на товары числа отображаются в нечитаемом виде. Например, стоимость товара 1500000 выводится как "1500000", а хотелось бы видеть "1 500 000" или "1,500,000". Я пробовал использовать toLocaleString(), но он почему-то не работает для всех чисел корректно. Вот мой код: ```javascript let price = 1500000; console.log(price.toLocaleString()); // Выводит "1500000" (без разделителей) ``` При этом у меня в браузере русская локаль. Я также пробовал передавать параметры: ```javascript console.log(price.toLocaleString('ru-RU')); // Всё равно "1500000" ``` Может быть, я что-то делаю не так? Или есть другой способ добавить разделители тысяч? Нужно, чтобы решение работало во всех современных браузерах, включая мобильные версии. Также хотелось бы, чтобы можно было легко менять символ разделителя (пробел или запятая) и количество знаков после запятой для валют. Пожалуйста, подскажите оптимальный способ форматирования чисел с разделением тысяч, желательно без использования сторонних библиотек. Спасибо! <<>>

Правильное использование toLocaleString()

Проблема в вашем коде в том, что вы вызываете метод toLocaleString() на объекте Number, но не передаёте опции форматирования. По умолчанию метод использует системную локаль браузера, которая может не поддерживать разделение тысяч для целых чисел. Вот правильный способ:

let price = 1500000;
// Явно указываем локаль и опции
console.log(price.toLocaleString('ru-RU', { 
    useGrouping: true // Включаем группировку разрядов
})); 
// Выведет: "1 500 000" (с пробелами для русской локали)

Универсальное решение с Intl.NumberFormat

Для большей гибкости используйте Intl.NumberFormat — это стандартный API форматирования чисел в JavaScript, доступный во всех современных браузерах:

// Создаём форматтер один раз
const formatter = new Intl.NumberFormat('ru-RU', {
    style: 'decimal', // или 'currency' для валют
    useGrouping: true,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
});

// Используем для любого числа
console.log(formatter.format(1500000));    // "1 500 000,00"
console.log(formatter.format(12345.6789)); // "12 345,68"
console.log(formatter.format(0.99));       // "0,99"

Форматирование валют

Для цен в магазине лучше использовать стиль currency:

const currencyFormatter = new Intl.NumberFormat('ru-RU', {
    style: 'currency',
    currency: 'RUB',
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
});

console.log(currencyFormatter.format(1500000)); // "1 500 000 ₽"
console.log(currencyFormatter.format(99.99));   // "99,99 ₽"

Кастомное форматирование с возможностью выбора разделителя

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

function formatNumber(num, options = {}) {
    const {
        thousandsSeparator = ' ',  // по умолчанию пробел
        decimalSeparator = ',',    // по умолчанию запятая
        decimalPlaces = 0          // количество знаков после запятой
    } = options;

    // Разделяем целую и дробную части
    let [integerPart, decimalPart] = num.toFixed(decimalPlaces).split('.');
    
    // Добавляем разделители тысяч
    integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
    
    // Собираем результат
    return decimalPart 
        ? integerPart + decimalSeparator + decimalPart 
        : integerPart;
}

// Примеры использования:
console.log(formatNumber(1500000));                // "1 500 000"
console.log(formatNumber(1500000, { thousandsSeparator: ',' })); // "1,500,000"
console.log(formatNumber(12345.6789, { decimalPlaces: 2 }));     // "12 345,68"

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

  • Вы не указали useGrouping: true — это ключевая опция для включения разделителей тысяч
  • Локаль браузера могла быть не русской, и для неё группировка могла быть отключена по умолчанию
  • Метод toLocaleString() без опций использует настройки системы, которые могут отличаться на разных устройствах

Рекомендую использовать Intl.NumberFormat — это более современный и гибкий API, который даёт полный контроль над форматированием. Он поддерживается всеми браузерами, включая IE11 (с некоторыми ограничениями).

<<>>

Простой регулярный подход без Intl API

Если вам нужно минималистичное решение без использования локалей, можно воспользоваться регулярным выражением:

function thousandSeparator(num) {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
}

console.log(thousandSeparator(1500000)); // "1 500 000"
console.log(thousandSeparator(123456789)); // "123 456 789"

Этот метод работает только с целыми числами. Для дробных чисел можно расширить функцию:

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

console.log(formatNumber(1234567.89)); // "1 234 567.89"
console.log(formatNumber(1234567.89, ',')); // "1,234,567.89"

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

  • Если нужно поддерживать очень старые браузеры (IE9 и ниже)
  • Если нужно быстрое решение без загрузки дополнительных локалей
  • Для простых случаев, когда не требуется форматирование валют

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