Форматирование строк в JavaScript: аналог printf или String.Format
Краткий ответ
В JavaScript нет встроенной функции, полностью аналогичной printf или String.Format. Однако есть несколько элегантных способов решить эту задачу: от использования шаблонных строк (самый современный и рекомендуемый способ) до написания собственной функции или подключения лёгкой библиотеки.
1. Шаблонные строки (Template Literals) — лучший вариант
Стандарт ES6 (2015) ввёл шаблонные строки. Они решают 90% задач форматирования:
const name = "Алексей";
const count = 42;
const pi = Math.PI;
// Базовая интерполяция
const result = `Привет, ${name}! У тебя ${count} новых сообщений.`;
console.log(result); // "Привет, Алексей! У тебя 42 новых сообщения."
// Можно использовать выражения
const formattedPi = `PI с двумя знаками: ${pi.toFixed(2)}`;
console.log(formattedPi); // "PI с двумя знаками: 3.14"
// Многострочные строки без \n
const multiline = `
Строка 1: ${name}
Строка 2: ${count}
`;
Плюсы: нативный синтаксис, безопасность (экранирование), поддержка любых выражений. Минусы: нет встроенного форматирования чисел (например, %02d), но это решается методами .toFixed(), .padStart() и т.д.
2. Собственная функция sprintf (легковесная)
Если вам нужен точный аналог printf, напишите простую функцию:
function sprintf(format, ...args) {
return format.replace(/%([sd])/g, (match, type) => {
const value = args.shift();
switch (type) {
case 's': return String(value);
case 'd': return parseInt(value, 10).toString();
default: return match;
}
});
}
// Пример:
console.log(sprintf("Привет, %s! У тебя %d сообщений.", "Мир", 42));
// "Привет, Мир! У тебя 42 сообщений."
Этот код можно расширить для поддержки %f, %x, ширины поля и т.д.
3. Использование библиотек
Для сложного форматирования (даты, валюты, локализация) лучше взять готовое решение:
- sprintf-js — лёгкая библиотека (2KB), точная копия C-шного
sprintf. Установка:npm install sprintf-js. - Intl.NumberFormat и Intl.DateTimeFormat — встроенные объекты для локализованного форматирования чисел и дат.
// Пример с sprintf-js
const sprintf = require('sprintf-js').sprintf;
console.log(sprintf("PI = %.2f, HEX = %X", Math.PI, 255));
// "PI = 3.14, HEX = FF"
// Пример с Intl
const formatter = new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB'
});
console.log(formatter.format(12345.67)); // "12 345,67 ₽"
4. Альтернатива: метод replace с регулярным выражением
Можно имитировать String.Format из C#:
String.prototype.format = function(...args) {
return this.replace(/{(\d+)}/g, (match, index) => {
return args[index] !== undefined ? args[index] : match;
});
};
console.log("Привет, {0}! У тебя {1} сообщений.".format("Мир", 42));
// "Привет, Мир! У тебя 42 сообщений."
Итоговый совет
Для большинства повседневных задач используйте шаблонные строки — они читаемы, безопасны и не требуют дополнительных зависимостей. Если вам нужен точный printf (например, для форматирования чисел с ведущими нулями), добавьте библиотеку sprintf-js или напишите свою мини-функцию.
Дополнительный подход: форматирование чисел с помощью Intl и padStart
Если вам не нужна полноценная библиотека, а только форматирование чисел (добавление ведущих нулей, фиксированное количество знаков после запятой), можно комбинировать шаблонные строки со встроенными методами:
function formatNumber(num, width = 2) {
return String(num).padStart(width, '0');
}
function formatCurrency(amount) {
return new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB',
minimumFractionDigits: 2
}).format(amount);
}
// Пример использования:
const id = 7;
const price = 12345.5;
console.log(`Заказ №${formatNumber(id, 4)} на сумму ${formatCurrency(price)}`);
// "Заказ №0007 на сумму 12 345,50 ₽"
Этот подход не требует сторонних библиотек, полностью контролируется разработчиком и легко расширяется. Для дат используйте Intl.DateTimeFormat:
const date = new Date();
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(`Сегодня: ${formatter.format(date)}`);
// "Сегодня: 15 марта 2025 г."
Таким образом, вы получаете гибкость printf без потери производительности и читаемости.