НейроАгент

Эквивалент printf() в JavaScript: Полное руководство

Узнайте альтернативы JavaScript для printf() в C/PHP и String.Format() в C#/Java. Изучите встроенные API Intl, легковесные библиотеки вроде sprintf-js и пользовательские реализации форматирования чисел с разделителями тысяч.

Вопрос

Какой JavaScript-эквивалент существует для функции printf() из C/PHP или String.Format() из C#/Java?

Я ищу JavaScript-функцию для форматирования строк, похожую на то, как работает printf() в C/PHP или String.Format() в C#/Java. Моя основная потребность - форматирование чисел с разделителями тысяч, но я также хотел бы найти решение, которое может обрабатывать различные параметры форматирования, включая даты.

Я знаю, что библиотека Ajax от Microsoft предоставляет реализацию String.Format(), но я предпочитаю легковесное решение, которое не требует всей библиотеки.

НейроАгент

В JavaScript нет встроенных функций printf() или String.Format(), как в C/PHP или C#/Java, но доступно несколько легковесных решений. Наиболее распространенные подходы включают использование встроенного API Intl.NumberFormat для форматирования чисел с разделителями тысяч или создание пользовательских функций форматирования, поддерживающих различные шаблоны.

Содержание

Встроенные решения JavaScript

JavaScript предоставляет несколько нативных API, которые могут заменить функциональность printf/String.Format без необходимости использования внешних библиотек.

API Intl.NumberFormat

Объект Intl.NumberFormat — это современное встроенное решение для форматирования чисел с разделителями тысяч и форматирования, зависящего от локали:

javascript
const number = 1234567.89;

// Базовое форматирование чисел с разделителями тысяч
const formatted = new Intl.NumberFormat('en-US').format(number);
console.log(formatted); // "1,234,567.89"

// Для разных локалей
const germanFormat = new Intl.NumberFormat('de-DE').format(number);
console.log(germanFormat); // "1.234.567,89"

// С форматированием валюты
const currencyFormat = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(number);
console.log(currencyFormat); // "$1,234,567.89"

Шаблонные литералы с функциями-тегами

Современные шаблонные литералы JavaScript с функциями-тегами предоставляют гибкий способ создания форматированных строк:

javascript
// Простой шаблонный литерал
const name = "Мир";
const greeting = `Привет, ${name}!`;

// Более сложное форматирование с пользовательской функцией-тегом
function format(strings, ...values) {
  return strings.reduce((result, string, i) => {
    return result + string + (values[i] || '');
  }, '');
}

const result = format`Цена составляет $${1234.56}, а количество равно ${1000}`;
console.log(result); // "Цена составляет $1234.56, а количество равно 1000"

Легковесные библиотеки форматирования строк

Несколько легковесных библиотек предоставляют функциональность printf/String.Format без излишней тяжеловесности больших фреймворков.

sprintf-js

Популярная легковесная реализация функциональности sprintf:

javascript
// Установка: npm install sprintf-js
const sprintf = require('sprintf-js').sprintf;

// Базовое форматирование строк
const formatted = sprintf("Привет %s, у вас %d сообщений", "Алиса", 5);
console.log(formatted); // "Привет Алиса, у вас 5 сообщений"

// Форматирование чисел с разделителями тысяч
const number = 1234567;
const formattedNum = sprintf("%'d", number); // Использование ' в качестве разделителя тысяч
console.log(formattedNum); // "1,234,567"

string-format

Еще один легковесный вариант с простым синтаксисом:

javascript
// Установка: npm install string-format
const format = require('string-format');

// Базовое использование
const result = format("Привет {0}, у вас {1} сообщений", "Алиса", 5);
console.log(result); // "Привет Алиса, у вас 5 сообщений"

// Именованные параметры
const namedResult = format("Привет {name}, у вас {count} сообщений", {
  name: "Алиса", 
  count: 5
});
console.log(namedResult); // "Привет Алиса, у вас 5 сообщений"

util.format

Node.js предоставляет встроенный метод util.format, похожий на printf:

javascript
const util = require('util');

const formatted = util.format("Привет %s, у вас %d сообщений", "Алиса", 5);
console.log(formatted); // "Привет Алиса, у вас 5 сообщений"

Реализация пользовательской функции форматирования

Вы можете создать собственную легковесную функцию форматирования, охватывающую функциональность, похожую на printf:

javascript
function printf(format, ...args) {
  return format.replace(/%([%sdf])/g, function(match, type) {
    const value = args.shift();
    switch(type) {
      case '%': return '%';
      case 's': return String(value);
      case 'd': return Math.floor(value);
      case 'f': return parseFloat(value).toFixed(2);
      default: return match;
    }
  });
}

// Примеры использования
const result1 = printf("Привет %s, у вас %d сообщений", "Алиса", 5);
const result2 = printf("Цена составляет $%f", 1234.567);
console.log(result1); // "Привет Алиса, у вас 5 сообщений"
console.log(result2); // "Цена составляет $1234.57"

Для более комплексного форматирования, вот расширенная версия:

javascript
function formatString(format, ...args) {
  return format.replace(/%(%)|(%(\d+)\$)?([-+ 0#])*(\d+)?(?:\.(\d+))?([diufFeEgGcsb])|{(\d+)(?::([^}]+))?}/g, function(match, literal, positional, pos, flags, width, precision, type, index, formatSpec) {
    let value;
    
    // Обработка позиционных аргументов в стиле printf
    if (positional) {
      value = args[parseInt(pos) - 1];
    } 
    // Обработка стиля шаблонных литералов {индекс}
    else if (index !== undefined) {
      value = args[parseInt(index)];
    }
    // Обработка последовательных аргументов в стиле printf
    else if (!literal) {
      value = args.shift();
    }
    
    if (value === undefined) return match;
    
    // Форматирование в зависимости от типа
    switch(type) {
      case '%': return '%';
      case 's': return String(value);
      case 'd': case 'i': return Math.floor(value).toLocaleString();
      case 'f': case 'F': return parseFloat(value).toFixed(precision || 2).toLocaleString();
      case 'e': case 'E': return parseFloat(value).toExponential(precision || 2);
      case 'g': case 'G': return parseFloat(value).toPrecision(precision || 6);
      case 'c': return value;
      case 'b': return parseInt(value).toString(2);
      default: return String(value);
    }
  });
}

// Примеры использования
console.log(formatString("Привет %s, баланс: $%d", "Алиса", 1234567));
console.log(formatString("Точность: %0.2f", 3.14159));
console.log(formatString("Научное: %e", 1000000));
console.log(formatString("Шаблон: {0} имеет {1:,d} очков", "Боб", 9876543));

Форматирование чисел с разделителями тысяч

Для вашей основной необходимости форматирования чисел с разделителями тысяч, вот несколько подходов:

Использование Intl.NumberFormat (рекомендуется)

javascript
function formatNumber(number, locale = 'en-US') {
  return new Intl.NumberFormat(locale).format(number);
}

// Использование
console.log(formatNumber(1234567)); // "1,234,567"
console.log(formatNumber(1234567.89, 'de-DE')); // "1.234.567,89"
console.log(formatNumber(1234567, 'fr-FR')); // "1 234 567"

Использование пользовательского форматирования чисел

javascript
function formatNumberWithSeparators(number, separator = ',') {
  return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator);
}

// Использование
console.log(formatNumberWithSeparators(1234567)); // "1,234,567"
console.log(formatNumberWithSeparators(1234567, '.')); // "1.234.567"

Комбинирование с другим форматированием чисел

javascript
function formatCurrency(amount, currency = 'USD', locale = 'en-US') {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency: currency,
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  }).format(amount);
}

function formatPercent(value, decimals = 2, locale = 'en-US') {
  return new Intl.NumberFormat(locale, {
    style: 'percent',
    minimumFractionDigits: decimals,
    maximumFractionDigits: decimals
  }).format(value / 100);
}

// Использование
console.log(formatCurrency(1234567.89)); // "$1,234,567.89"
console.log(formatPercent(0.1567)); // "15.67%"

Варианты форматирования даты

JavaScript также предоставляет надежное форматирование даты через API Intl.DateTimeFormat:

javascript
function formatDate(date, locale = 'en-US', options = {}) {
  const defaultOptions = {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  };
  
  return new Intl.DateTimeFormat(locale, { ...defaultOptions, ...options }).format(date);
}

// Примеры использования
const now = new Date();
console.log(formatDate(now)); 
// "31 декабря 2024 г., 23:59:59"

console.log(formatDate(now, 'de-DE', { 
  year: 'numeric', 
  month: 'short', 
  day: 'numeric' 
})); 
// "31. Dez. 2024"

console.log(formatDate(now, 'ja-JP', { 
  era: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'long'
})); 
// "2024年12月31日 火曜日"

Для форматирования даты в стиле printf, вы можете расширить пользовательскую функцию форматирования:

javascript
function formatDateTime(format, date = new Date(), ...args) {
  const pad = (num, width = 2) => num.toString().padStart(width, '0');
  const dateObj = new Date(date);
  
  // Спецификаторы формата даты
  const formatMap = {
    '%Y': dateObj.getFullYear(),
    '%y': dateObj.getFullYear() % 100,
    '%m': pad(dateObj.getMonth() + 1),
    '%d': pad(dateObj.getDate()),
    '%H': pad(dateObj.getHours()),
    '%M': pad(dateObj.getMinutes()),
    '%S': pad(dateObj.getSeconds()),
    '%A': dateObj.toLocaleDateString('ru-RU', { weekday: 'long' }),
    '%B': dateObj.toLocaleDateString('ru-RU', { month: 'long' }),
    '%b': dateObj.toLocaleDateString('ru-RU', { month: 'short' }),
  };
  
  // Замена спецификаторов формата
  let result = format;
  for (const [spec, value] of Object.entries(formatMap)) {
    result = result.replace(new RegExp(spec.replace('%', '\\%'), 'g'), value);
  }
  
  // Обработка оставшегося форматирования в стиле printf
  return result.replace(/%(%)|(%(\d+)\$)?([-+ 0#])*(\d+)?(?:\.(\d+))?([diufFeEgGcsb])/g, function(match, literal, positional, pos, flags, width, precision, type) {
    if (literal) return '%';
    return args.shift() || '';
  });
}

// Использование
console.log(formatDateTime("Сегодня %A, %B %d, %Y"));
console.log(formatDateTime("Время: %H:%M:%S", new Date(), "дополнительные", "аргументы"));

Сравнение решений

Решение Плюсы Минусы Лучше всего подходит для
Intl.NumberFormat Встроенный, зависящий от локали, без зависимостей Ограничен форматированием чисел Современные приложения, требующие международного форматирования чисел
sprintf-js Полная совместимость с printf, легковесный Требует внешней зависимости Разработчикам C/PHP, знакомым с синтаксисом
Пользовательская функция форматирования Полный контроль, без зависимостей Требует поддержки Проектов с конкретными, специализированными потребностями форматирования
Шаблонные литералы Нативный JavaScript, читаемый Ограниченные возможности форматирования Простых задач интерполяции строк
util.format Встроенный (Node.js), знакомый синтаксис Только для Node.js Серверных приложений на JavaScript

Для ваших конкретных потребностей я рекомендую начать с Intl.NumberFormat для форматирования чисел с разделителями тысяч, так как он встроенный, зависит от локали и не требует внешних зависимостей. Для более комплексного форматирования строк, библиотеки вроде sprintf-js предоставляют отличную совместимость со стилем printf, оставаясь легковесными.

Заключение

JavaScript предоставляет несколько отличных альтернатив printf() из C/PHP и String.Format() из C#/Java, варьирующихся от встроенных API до легковесных библиотек. Для вашей основной необходимости форматирования чисел с разделителями тысяч, API Intl.NumberFormat является рекомендуемым современным решением. Для более комплексного форматирования строк, библиотеки вроде sprintf-js предлагают функциональность в стиле printf без необходимости использования больших фреймворков. Подход с пользовательской реализацией дает полный контроль над поведением форматирования при минимальном размере.

Основные рекомендации:

  1. Используйте Intl.NumberFormat для форматирования чисел с разделителями тысяч и поддержки локалей
  2. Рассмотрите sprintf-js для комплексного форматирования строк в стиле printf
  3. Реализуйте пользовательские функции форматирования для специфических потребностей проекта
  4. Используйте шаблонные литералы для простых задач интерполяции строк
  5. Комбинируйте Intl.NumberFormat с Intl.DateTimeFormat для последовательного международного форматирования

Эти решения предоставляют необходимую функциональность, сохраняя легковесный подход, который вы предпочитаете, и устраняя необходимость в больших фреймворках, таких как библиотека Ajax от Microsoft.