Intl.NumberFormat — форматирование чисел в JavaScript

02 октября 2026
Автор

Антон Ларичев

Что такое Intl.NumberFormat

Intl.NumberFormat — встроенный конструктор JavaScript, входящий в состав API интернационализации (Intl). Он позволяет форматировать числа в соответствии с правилами конкретной локали: разделители групп разрядов, десятичный разделитель, символы валют, единицы измерения и многое другое.

До появления Intl разработчики писали собственные функции форматирования или тянули тяжёлые библиотеки. Сегодня браузеры и Node.js поддерживают этот API нативно, без сторонних зависимостей.

const formatter = new Intl.NumberFormat('ru-RU');
console.log(formatter.format(1234567.89)); // "1 234 567,89"

Курс по теме

Основы JavaScript — курс

40 000+ студентов · рейтинг 4.8 · гарантия возврата 30 дней

Создание экземпляра

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

new Intl.NumberFormat(locales, options)
  • locales — строка или массив строк с BCP 47-тегами локали ('ru-RU', 'en-US', 'de-DE'). Если передать undefined или опустить, используется системная локаль.
  • options — объект с настройками форматирования.
// Одна локаль
const ruFormatter = new Intl.NumberFormat('ru-RU');

// Массив локалей — движок выберет наиболее подходящую
const formatter = new Intl.NumberFormat(['ru-RU', 'en-US']);

// Системная локаль
const sysFormatter = new Intl.NumberFormat();

Метод format

Основной метод — format(number). Он принимает число и возвращает отформатированную строку.

const en = new Intl.NumberFormat('en-US');
const ru = new Intl.NumberFormat('ru-RU');
const de = new Intl.NumberFormat('de-DE');

const num = 9876543.21;

console.log(en.format(num)); // "9,876,543.21"
console.log(ru.format(num)); // "9 876 543,21"
console.log(de.format(num)); // "9.876.543,21"

Каждая локаль применяет собственные правила: в русской — пробел как разделитель разрядов, запятая как десятичный разделитель; в американской — наоборот.

Быстрый вызов без создания экземпляра

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

console.log(Intl.NumberFormat('ru-RU').format(42000)); // "42 000"

Но если нужно форматировать много чисел — создайте экземпляр один раз и переиспользуйте его. Создание объекта Intl.NumberFormat — операция дорогая.

Опция style — стиль форматирования

Опция style определяет базовый режим форматирования.

decimal — обычное число (по умолчанию)

const fmt = new Intl.NumberFormat('ru-RU', { style: 'decimal' });
console.log(fmt.format(12345.6)); // "12 345,6"

currency — валюта

При использовании style: 'currency' обязательно нужно указать currency — код валюты по ISO 4217.

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

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

const eur = new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR',
});

console.log(rub.format(1500));   // "1 500,00 ₽"
console.log(usd.format(1500));   // "1 500,00 $"
console.log(eur.format(1500));   // "1.500,00 €"

Отображением символа валюты управляет опция currencyDisplay:

const opts = { style: 'currency', currency: 'USD' };

// symbol (по умолчанию) — символ валюты
new Intl.NumberFormat('en-US', { ...opts, currencyDisplay: 'symbol' }).format(99);
// "$99.00"

// narrowSymbol — короткий символ без привязки к стране
new Intl.NumberFormat('en-US', { ...opts, currencyDisplay: 'narrowSymbol' }).format(99);
// "$99.00"

// code — ISO-код
new Intl.NumberFormat('en-US', { ...opts, currencyDisplay: 'code' }).format(99);
// "USD 99.00"

// name — полное название
new Intl.NumberFormat('ru-RU', { ...opts, currencyDisplay: 'name' }).format(99);
// "99,00 доллара США"

percent — проценты

const pct = new Intl.NumberFormat('ru-RU', { style: 'percent' });

console.log(pct.format(0.75));  // "75%"
console.log(pct.format(1.5));   // "150%"
console.log(pct.format(0.001)); // "0%"

Обратите внимание: значение умножается на 100. Чтобы отобразить 75%, нужно передать 0.75.

unit — единицы измерения

const speed = new Intl.NumberFormat('ru-RU', {
  style: 'unit',
  unit: 'kilometer-per-hour',
});

const weight = new Intl.NumberFormat('ru-RU', {
  style: 'unit',
  unit: 'kilogram',
  unitDisplay: 'long',
});

console.log(speed.format(120));  // "120 км/ч"
console.log(weight.format(5));   // "5 килограммов"

Опция unitDisplay управляет формой записи единицы: 'short' (по умолчанию), 'narrow', 'long'.

Полный список допустимых единиц можно найти в спецификации Unicode CLDR — он включает byte, megabyte, celsius, fahrenheit, meter, mile, liter, gallon и десятки других.

Контроль количества знаков

minimumFractionDigits и maximumFractionDigits

const price = new Intl.NumberFormat('ru-RU', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
});

console.log(price.format(10));      // "10,00"
console.log(price.format(10.5));    // "10,50"
console.log(price.format(10.559));  // "10,56" — округление

minimumIntegerDigits

Задаёт минимальное количество цифр до десятичного разделителя. Число дополняется нулями слева.

const fmt = new Intl.NumberFormat('en-US', { minimumIntegerDigits: 3 });
console.log(fmt.format(7));   // "007"
console.log(fmt.format(42));  // "042"
console.log(fmt.format(100)); // "100"

minimumSignificantDigits и maximumSignificantDigits

Значимые цифры — альтернатива фиксированному количеству знаков после запятой.

const sig = new Intl.NumberFormat('en-US', {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 5,
});

console.log(sig.format(1));          // "1.00"
console.log(sig.format(1.23456789)); // "1.2346"
console.log(sig.format(12345.6789)); // "12,346"

Опция notation — вид записи числа

standard (по умолчанию)

Обычная запись числа без изменений.

scientific

Научная нотация: число × 10^n.

const sci = new Intl.NumberFormat('en-US', { notation: 'scientific' });
console.log(sci.format(123456789)); // "1.235E8"
console.log(sci.format(0.000042));  // "4.2E-5"

engineering

Похожа на научную, но показатель степени всегда кратен 3.

const eng = new Intl.NumberFormat('en-US', { notation: 'engineering' });
console.log(eng.format(123456789)); // "123.457E6"

compact

Сокращённая форма — удобна для отображения больших чисел в интерфейсах.

const compact = new Intl.NumberFormat('ru-RU', { notation: 'compact' });
console.log(compact.format(1000));        // "1 тыс."
console.log(compact.format(1500000));     // "1,5 млн"
console.log(compact.format(2300000000));  // "2,3 млрд"

// compactDisplay: 'long' даёт полные слова
const compactLong = new Intl.NumberFormat('ru-RU', {
  notation: 'compact',
  compactDisplay: 'long',
});
console.log(compactLong.format(1500000)); // "1,5 миллиона"

Знак числа — опция signDisplay

По умолчанию знак минус ставится только для отрицательных чисел. Опция signDisplay меняет это поведение.

const always = new Intl.NumberFormat('en-US', { signDisplay: 'always' });
console.log(always.format(42));  // "+42"
console.log(always.format(-42)); // "-42"
console.log(always.format(0));   // "+0"

// exceptZero — знак везде, кроме нуля
const excZero = new Intl.NumberFormat('en-US', { signDisplay: 'exceptZero' });
console.log(excZero.format(42));  // "+42"
console.log(excZero.format(0));   // "0"
console.log(excZero.format(-42)); // "-42"

// negative — знак только у отрицательных (поведение по умолчанию)
// never — знак никогда не показывается

Метод formatToParts

formatToParts(number) возвращает массив объектов, каждый из которых описывает отдельный элемент числа. Это полезно, когда нужно стилизовать части числа по-разному.

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

const parts = fmt.formatToParts(1234.56);
console.log(parts);
/*
[
  { type: 'integer',          value: '1'    },
  { type: 'group',            value: '\u00A0' }, // неразрывный пробел
  { type: 'integer',          value: '234'  },
  { type: 'decimal',          value: ','    },
  { type: 'fraction',         value: '56'   },
  { type: 'literal',          value: '\u00A0' },
  { type: 'currency',         value: '₽'    },
]
*/

Пример применения — подсветка дробной части:

function formatWithHighlight(number, locale, options) {
  const fmt = new Intl.NumberFormat(locale, options);
  return fmt.formatToParts(number).map(({ type, value }) => {
    if (type === 'fraction') {
      return `<span class="fraction">${value}</span>`;
    }
    return value;
  }).join('');
}

console.log(formatWithHighlight(1234.56, 'ru-RU', { minimumFractionDigits: 2 }));
// "1 234,<span class="fraction">56</span>"

Метод formatRange

formatRange(startNumber, endNumber) форматирует диапазон чисел. Метод относительно новый, появился в 2022 году.

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

console.log(price.formatRange(1000, 2000)); // "1 000 – 2 000 ₽"
console.log(price.formatRange(500, 500));   // "~500 ₽" — одинаковые значения

Метод formatRangeToParts аналогичен formatToParts, но для диапазонов.

Метод resolvedOptions

Позволяет узнать, какие опции действительно были применены после нормализации и подбора локали.

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

console.log(fmt.resolvedOptions());
/*
{
  locale: 'ru-RU',
  numberingSystem: 'latn',
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'symbol',
  currencySign: 'standard',
  minimumIntegerDigits: 1,
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
  useGrouping: 'auto',
  notation: 'standard',
  signDisplay: 'auto'
}
*/

Практические примеры

Форматирование цены в интернет-магазине

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

const saleFormatter = new Intl.NumberFormat('ru-RU', {
  style: 'currency',
  currency: 'RUB',
  maximumFractionDigits: 0,
  signDisplay: 'never',
});

const products = [
  { name: 'Ноутбук', price: 89990 },
  { name: 'Мышь',    price: 2499  },
  { name: 'Клавиатура', price: 4990 },
];

products.forEach(({ name, price }) => {
  console.log(`${name}: ${priceFormatter.format(price)}`);
});
// Ноутбук: 89 990 ₽
// Мышь: 2 499 ₽
// Клавиатура: 4 990 ₽

Статистика с компактной нотацией

const statFormatter = new Intl.NumberFormat('ru-RU', {
  notation: 'compact',
  maximumSignificantDigits: 3,
});

const stats = {
  views:     4320000,
  likes:     87400,
  comments:  1230,
  followers: 950000,
};

Object.entries(stats).forEach(([key, val]) => {
  console.log(`${key}: ${statFormatter.format(val)}`);
});
// views: 4,32 млн
// likes: 87,4 тыс.
// comments: 1,23 тыс.
// followers: 950 тыс.

Таблица курсов валют

function formatCurrency(amount, currency, locale = 'ru-RU') {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 4,
  }).format(amount);
}

const rates = [
  { currency: 'USD', rate: 89.45 },
  { currency: 'EUR', rate: 97.12 },
  { currency: 'CNY', rate: 12.34 },
];

rates.forEach(({ currency, rate }) => {
  console.log(`1 ${currency} = ${formatCurrency(rate, 'RUB')}`);
});
// 1 USD = 89,45 ₽
// 1 EUR = 97,12 ₽
// 1 CNY = 12,34 ₽

Процентные изменения с явным знаком

const changeFormatter = new Intl.NumberFormat('ru-RU', {
  style: 'percent',
  minimumFractionDigits: 1,
  maximumFractionDigits: 1,
  signDisplay: 'exceptZero',
});

const changes = [0.034, -0.018, 0, 0.127, -0.053];

changes.forEach(change => {
  const sign = change > 0 ? '↑' : change < 0 ? '↓' : '→';
  console.log(`${sign} ${changeFormatter.format(change)}`);
});
// ↑ +3,4%
// ↓ -1,8%
// → 0,0%
// ↑ +12,7%
// ↓ -5,3%

Производительность: переиспользуйте экземпляры

Создание экземпляра Intl.NumberFormat включает парсинг локали, загрузку данных CLDR и компиляцию правил форматирования. Эта операция занимает значительно больше времени, чем сам вызов format.

// Плохо: создаём новый объект при каждом вызове
function formatBad(number) {
  return new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB' }).format(number);
}

// Хорошо: создаём один раз, переиспользуем
const rubFormatter = new Intl.NumberFormat('ru-RU', {
  style: 'currency',
  currency: 'RUB',
});

function formatGood(number) {
  return rubFormatter.format(number);
}

Для динамических локалей используйте кэш:

const formatterCache = new Map();

function getFormatter(locale, options) {
  const key = `${locale}-${JSON.stringify(options)}`;
  if (!formatterCache.has(key)) {
    formatterCache.set(key, new Intl.NumberFormat(locale, options));
  }
  return formatterCache.get(key);
}

// При повторном вызове с теми же параметрами объект не создаётся заново
getFormatter('ru-RU', { style: 'currency', currency: 'RUB' }).format(1500);

Поддержка браузерами

Intl.NumberFormat поддерживается во всех современных браузерах и Node.js начиная с версии 0.12. Некоторые опции появились позже:

  • notation, compactDisplay — Chrome 77+, Firefox 78+, Safari 14.1+
  • style: 'unit' — Chrome 77+, Firefox 78+, Safari 14.1+
  • formatRange — Chrome 106+, Firefox 116+, Safari 15.4+

Для старых окружений существуют полифиллы, например @formatjs/intl-numberformat.

Итог

Intl.NumberFormat — мощный и гибкий инструмент, который избавляет от необходимости писать велосипеды для форматирования чисел. Он учитывает особенности сотен локалей, поддерживает валюты, проценты, единицы измерения и компактную нотацию. Главные практические правила: создавайте экземпляр один раз и переиспользуйте его, выбирайте нужный style в зависимости от контекста, а formatToParts используйте когда нужна тонкая стилизация отдельных частей числа.

Чтобы глубже разобраться с JavaScript и встроенными API браузера, приходите на курс «JavaScript с нуля» на PurpleSchool.

Стрелочка влевоОбъекты в JavaScriptObject.hasOwn вместо hasOwnPropertyСтрелочка вправо

Постройте личный план изучения Javascript до уровня Middle — бесплатно!

Javascript — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Javascript

Как работает метод trim() - JavaScriptКак работает метод toUpperCase() - JavaScriptКак работает метод toLowerCase() - JavaScriptКак работает метод substring() - JavaScriptКак работает метод startsWith() - JavaScriptКак работает метод split() - JavaScriptКак работает метод slice() - JavaScriptКак работает метод search() - JavaScriptКак работает метод replaceAll() - JavaScriptКак работает метод replace() - JavaScriptКак работает метод repeat() - JavaScriptКак работает метод padStart() - JavaScriptКак работает метод matchAll() - JavaScriptКак работает метод match() - JavaScriptКак работает метод padEnd() - JavaScriptКак работает метод localeCompare() - JavaScriptКак работает свойство length - JavaScriptКак работает метод lastIndexOf() - JavaScriptКак работает метод indexOf() - JavaScriptКак работает метод includes() - JavaScriptКак работает метод fromCodePoint() - JavaScriptКак работает метод fromCharCode() - JavaScriptКак работает метод endsWith() - JavaScriptКак работает метод concat() - JavaScriptКак работает метод codePointAt() - JavaScriptКак работает метод charCodeAt() - JavaScriptКак работает метод charAt() - JavaScript
Итератор в JavaScript
try...catch в JavaScriptError в JavaScript
Событие wheel в JavaScriptСобытие unload в JavaScriptСобытие touch в JavaScriptСобытие submit в JavaScriptСобытие scroll в JavaScriptСобытие reset в JavaScriptМетод .preventDefault() в JavaScriptСобытие mouseover в JavaScriptСобытие mouseout в JavaScriptСобытие load в JavaScriptСобытие keyup в JavaScriptСобытие keydown в JavaScriptСобытие invalid в JavaScriptСобытийная модель Event в JavaScriptОбъект события Event в JavaScriptСобытие DOMContentLoaded в JavaScriptСобытие dblclick в JavaScriptСобытие input в JavaScriptСобытие click в JavaScriptСобытие change в JavaScriptJavaScript BroadcastChannel — межвкладочное взаимодействиеСобытие beforeunload в JavaScriptBroadcast Channel API в JavaScript
Error cause — цепочки ошибок в JavaScript
Методы массивов toSorted, toReversed и withКак работает метод reverse() - JavaScriptКак работает метод some() - JavaScriptКак работает метод reduce() - JavaScriptКак работает метод map() - JavaScriptКак работает метод isArray() - JavaScriptКак работает метод indexOf() - JavaScriptКак работает метод includes() - JavaScriptКак работает метод from() - JavaScriptКак работает метод forEach() - JavaScriptКак работает метод flatMap() - JavaScriptКак работает метод flat() - JavaScriptКак работает метод findIndex() - JavaScriptКак работает метод find() - JavaScriptКак работает метод filter() - JavaScriptКак работает метод every() - JavaScriptМассивы в JavaScriptArray.at, findLast, findLastIndex — новые методы массивов
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Основы JavaScript

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий