Форматирование чисел в строках шаблона (Javascript - ES6)

Мне было интересно, можно ли форматировать числа в строках шаблона Javascript, например:

var n = 5.1234;
console.log('This is a number: $.2d{n}');
// -> 5.12

Или, возможно,

var n = 5.1234;
console.log('This is a number: ${n.toString('.2d')}');
// -> 5.12

Очевидно, что этот синтаксис не работает, это всего лишь иллюстрация того, что я ищу.

Я знаю такие инструменты, как sprintf from underscore.string, но это похоже на то, что JS должно быть в состоянии сделать это, особенно учитывая силу строк шаблона.

РЕДАКТИРОВАТЬ

Как указано выше, я уже знаю о сторонних инструментах (например, sprintf) и настраиваемых функциях для этого. Аналогичные вопросы (например, эквивалент JavaScript для printf/String.Format) вообще не упоминают строки шаблонов, вероятно, потому, что их спрашивали до того, как строки шаблонов ES6 были вокруг. Мой вопрос специфичен для ES6 и не зависит от реализации. Я очень рад принять ответ "Нет, это невозможно", если это так, но что было бы здорово - это либо информация о новой функции ES6, которая предоставляет это, либо какое-то представление о том, есть ли такая функция на ее путь.

Ответ 1

Нет, ES6 не вводит никаких новых функций форматирования чисел, вам придется жить с существующим .toExponential(fractionDigits), .toFixed(fractionDigits), .toPrecision(precision), .toString([radix]) и toLocaleString(…) (который был обновлен, чтобы опционально поддерживать ECMA-402 Standard, хотя). Строки шаблонов не имеют никакого отношения к форматированию чисел, они просто отбрасывают вызов функции (если помечены тегами) или конкатенация строк (по умолчанию).

Если эти методы Number недостаточно для вас, вам придется сворачивать самостоятельно. Вы можете, конечно, написать свою функцию форматирования как тег строки шаблона, если вы этого хотите.

Ответ 2

Вы должны иметь возможность использовать метод toFixed() для числа:

var num = 5.1234;
var n = num.toFixed(2); 

Ответ 3

Если вы хотите использовать функции тегов ES6 здесь, как бы выглядела такая функция тега,

function d2(pieces) {
    var result = pieces[0];
    var substitutions = [].slice.call(arguments, 1);

    for (var i = 0; i < substitutions.length; ++i) {
        var n = substitutions[i];

        if (Number(n) == n) {
            result += Number(substitutions[i]).toFixed(2);
        } else {
            result += substitutions[i];
        }

        result += pieces[i + 1];
    }

    return result;
}

который затем может быть применен к строке шаблона,

d2'${some_float} (you can interpolate as many floats as you want) of ${some_string}';

который будет форматировать float и оставить строку в покое.

Ответ 4

Хотя форматирование с использованием интерполяции строк шаблонов недоступно как встроенное, вы можете получить эквивалентное поведение с Intl.NumberFormat:

const format = (num, fraction = 2) => new Intl.NumberFormat([], {
  minimumFractionDigits: fraction,
  maximumFractionDigits: fraction,
}).format(num);

format(5.1234); // -> '5.12'

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

(9.999).toFixed(2) // -> '10.00'

new Intl.NumberFormat([], {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2, // <- implicit rounding!
}).format(9.999) // -> '10.00'

Ответ 5

Здесь приведена полностью версия ES6 для решения Filip Allberg выше, используя параметры ES6 "rest". Единственное, чего не хватает, - это возможность изменять точность; это можно сделать, выполнив заводскую функцию. Оставленный как упражнение для читателя.

function d2(strs, ...args) {
    var result = strs[0];
    for (var i = 0; i < args.length; ++i) {
        var n = args[i];
        if (Number(n) == n) {
            result += Number(args[i]).toFixed(2);
        } else {
            result += args[i];
        }
        result += strs[i+1];
    }
    return result;
}

f=1.2345678;
s="a string";
console.log(d2'template: ${f} ${f*100} and ${s} (literal:${9.0001})');