Как форматировать числа с запятыми в качестве разделителей тысяч в JavaScript?
Я пытаюсь форматировать целые числа в JavaScript с запятыми в качестве разделителей тысяч. Например, я хочу преобразовать число 1234567 в “1,234,567”. Вот моя текущая реализация:
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))
Существует ли более простой или элегантный способ добиться этого? Было бы полезно, если бы решение также работало с числами с плавающей запятой, но это не является обязательным требованием. Решение не должно быть специфичным для локали при выборе между точками и запятыми.
JavaScript предлагает несколько встроенных методов для форматирования чисел с запятыми в качестве разделителей тысяч. Наиболее современный и элегантный подход — использование Intl.NumberFormat или toLocaleString(), которые обеспечивают нативную поддержку в браузерах без ручной манипуляции со строками. Для целых чисел, таких как 1234567, можно просто использовать 1234567.toLocaleString(), чтобы получить “1,234,567”.
Содержание
- Встроенные методы
- Подход с использованием регулярных выражений
- Ручная манипуляция со строками
- Сравнение методов
- Работа с числами с плавающей точкой
- Поддержка в браузерах и альтернативы
- Вопросы производительности
Встроенные методы
Использование toLocaleString()
Самый простой и элегантный способ — использование встроенного метода toLocaleString():
const number = 1234567;
const formatted = number.toLocaleString();
console.log(formatted); // "1,234,567"
Этот метод автоматически обрабатывает разделители тысяч и работает как с целыми числами, так и с числами с плавающей точкой:
console.log(1234567.89.toLocaleString()); // "1,234,567.89"
console.log(1000.toLocaleString()); // "1,000"
Использование Intl.NumberFormat
Для большего контроля и лучшей производительности в циклах используйте Intl.NumberFormat:
const formatter = new Intl.NumberFormat();
const formatted = formatter.format(1234567);
console.log(formatted); // "1,234,567"
Вы можете создать переиспользуемый форматтер:
// Создаем переиспользуемый форматтер
const currencyFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
// Используем его несколько раз
console.log(currencyFormatter.format(1234567)); // "$1,234,567.00"
Подход с использованием регулярных выражений
Ваша текущая реализация с использованием регулярных выражений функциональна, но может быть упрощена:
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
console.log(numberWithCommas(1234567)); // "1,234,567"
Этот шаблон регулярного выражения \B(?=(\d{3})+(?!\d)) использует позитивную опережающую проверку для поиска позиций, которые:
\B— Не находятся на границе слова (гарантирует, что мы не добавляем запятые в начале)(?=(\d{3})+)— За которыми следуют группы ровно из 3 цифр(?!\d)— Не за которыми следуют какие-либо цифры (гарантирует, что мы не добавляем запятые в конце)
Ручная манипуляция со строками
Для сред без поддержки Intl или когда требуется максимальный контроль:
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"
Сравнение методов
| Метод | Производительность | Поддержка в браузерах | Гибкость | Сложность кода |
|---|---|---|---|---|
toLocaleString() |
Хорошая | Все современные браузеры | Высокая | Очень простая |
Intl.NumberFormat |
Отличная (кэшируется) | Все современные браузеры | Очень высокая | Простая |
| Регулярные выражения | Умеренная | Все браузеры | Средняя | Умеренная |
| Ручной парсинг | Хорошая | Все браузеры | Низкая | Простая |
Работа с числами с плавающей точкой
Все встроенные методы автоматически обрабатывают десятичные точки:
const number = 1234567.8912;
// Используем toLocaleString
console.log(number.toLocaleString()); // "1,234,567.891"
// Используем Intl.NumberFormat
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 4
});
console.log(formatter.format(number)); // "1,234,567.8912"
Для ваших конкретных потребностей можно создать простую обертку:
function formatNumber(num) {
return num.toLocaleString();
}
// Работает и с целыми, и с дробными числами
console.log(formatNumber(1234567)); // "1,234,567"
console.log(formatNumber(1234567.89)); // "1,234,567.89"
Поддержка в браузерах и альтернативы
Современные браузеры (Chrome, Firefox, Safari, Edge)
Все современные браузеры полностью поддерживают Intl.NumberFormat и toLocaleString() с отличной производительностью.
Устаревшие браузеры (Internet Explorer)
Для старых браузеров можно использовать полифилл или вернуться к подходу с регулярными выражениями:
if (!window.Intl) {
// Резервный вариант для старых браузеров
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
} else {
// Современный подход
function formatNumber(num) {
return num.toLocaleString();
}
}
Решения на основе библиотек
Для расширенных потребностей в форматировании рассмотрите библиотеки:
Вопросы производительности
При форматировании большого количества значений Intl.NumberFormat наиболее эффективен при кэшировании:
// Кэшируем форматтер для лучшей производительности в циклах
const numberFormatter = new Intl.NumberFormat();
function formatManyNumbers(numbers) {
return numbers.map(num => numberFormatter.format(num));
}
// Значительно быстрее, чем вызов toLocaleString() каждый раз
const largeArray = Array.from({length: 1000}, (_, i) => i * 1000 + 123);
const formatted = formatManyNumbers(largeArray);
Заключение
Для вашего случая использования самым простым и элегантным решением является использование toLocaleString():
function numberWithCommas(x) {
return x.toLocaleString();
}
console.log(numberWithCommas(1234567)); // "1,234,567"
Ключевые выводы:
- Предпочтение встроенным методам:
toLocaleString()иIntl.NumberFormatявляются наиболее надежными и поддерживаемыми решениями - Производительность имеет значение: Для массовых операций кэшируйте экземпляры
Intl.NumberFormat - Совместимость: Современные браузеры отлично обрабатывают все эти методы
- Простота сложнее: Ваш подход с регулярными выражениями работает, но не так чист, как встроенные решения
- Гибкость: Встроенные методы автоматически обрабатывают как целые, так и дробные числа
Для большинства приложений toLocaleString() обеспечивает идеальный баланс простоты и функциональности. Если вам нужен больший контроль над параметрами форматирования или вы работаете с очень большими наборами данных, Intl.NumberFormat предлагает лучшую производительность и возможности настройки.