web-dev-qa-db-fra.com

Formatage des nombres dans les chaînes de modèle (Javascript - ES6)

Je me demandais s'il était possible de formater des nombres dans des chaînes de modèle Javascript, par exemple quelque chose comme:

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

Ou éventuellement

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

Cette syntaxe ne fonctionne évidemment pas, c'est juste une illustration du type de chose que je cherche.

Je connais des outils tels que sprintf de underscore.string, mais JS devrait pouvoir effectuer cette opération, en particulier compte tenu de la puissance des chaînes de modèles.

MODIFIER 

Comme indiqué ci-dessus, je connais déjà des outils tiers (par exemple, sprintf) et des fonctions personnalisées permettant de le faire. Des questions similaires (par exemple, équivalent JavaScript à printf/String.Format ) ne mentionnent pas du tout les chaînes de modèle, probablement parce qu'elles ont été posées avant la chaîne de modèle ES6. Ma question est spécifique à ES6 et est indépendante de la mise en œuvre. Je suis assez heureux d’accepter une réponse de "Non, ce n’est pas possible" si tel est le cas, mais ce qui serait formidable, c’est soit l’information sur une nouvelle fonctionnalité de l’ES6 offrant cette fonctionnalité, soit un aperçu de la pertinence de cette fonctionnalité façon.

21
aquavitae

Non, ES6 n'introduit pas de nouvelles fonctions de formatage des nombres, vous devez vivre avec les fonctions existantes .toExponential(fractionDigits) , .toFixed(fractionDigits) , .toPrecision(precision) , .toString([radix]) et toLocaleString(…) ( mis à jour pour prendre en charge éventuellement la norme ECMA-402 , cependant).
Les chaînes de modèle n'ont rien à voir avec le formatage des nombres, elles se contentent de décrire un appel de fonction (si étiqueté) ou une concaténation de chaîne (par défaut).

Si ces méthodes Number ne vous suffisent pas, vous devrez lancer la vôtre. Vous pouvez bien sûr écrire votre fonction de formatage en tant que balise de chaîne de modèle si vous le souhaitez.

21
Bergi

Vous devriez pouvoir utiliser la méthode toFixed () d'un nombre:

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

Si vous souhaitez utiliser les fonctions de balise ES6, voici à quoi ressemblerait une telle fonction de balise,

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;
}

qui peut ensuite être appliqué à une chaîne de modèle de cette manière,

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

cela formatera le float et laissera la chaîne seule. 

1
Filip Allberg

Ci-dessus, une version entièrement ES6 de la solution de Filip Allberg, qui utilise les paramètres "repos" de l'ES6. La seule chose qui manque, c'est de pouvoir varier la précision. cela pourrait être fait en faisant fonctionner l'usine. Gauche comme un exercice pour le lecteur.

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})`);

0
GaryO

Bien que le formatage à l'aide de l'interpolation de chaîne de modèle ne soit pas intégré, vous pouvez obtenir un comportement équivalent avec Intl.NumberFormat :

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

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

Notez que quelle que soit votre implémentation de choix, vous pouvez vous faire piquer par des erreurs d'arrondi:

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

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