Question

Je recherche un bon équivalent JavaScript du C / PHP printf() ou des programmeurs C # / Java, String.Format() (IFormatProvider pour .NET).

Mon exigence de base est un format de séparateur de milliers pour les nombres pour le moment, mais il serait bon d'utiliser quelque chose qui gère beaucoup de combinaisons (y compris les dates).

Je réalise que la bibliothèque Ajax de Microsoft fournit une version de <=>, mais nous ne voulons pas de la totalité des frais généraux de ce cadre.

Était-ce utile?

La solution

À partir de ES6, vous pouvez utiliser des chaînes de modèle:

let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

Voir la réponse ci-dessous de Kim pour plus de détails.

Sinon:

Essayez sprintf () pour JavaScript .

Si vous souhaitez réellement utiliser une méthode de formatage simple, ne & # 8217; ne faites pas les remplacements successivement mais faites-les simultanément.

La plupart des autres propositions mentionnées échouant lorsqu'une chaîne de remplacement d'un remplacement précédent contient également une séquence de format similaire à celle-ci:

"{0}{1}".format("{1}", "{0}")

Normalement, la sortie devrait être {1}{0} mais la sortie réelle est {1}{1}. Faites donc un remplacement simultané à la place, comme indiqué dans la fearphage & # 8217; suggestion de .

Autres conseils

En vous appuyant sur les solutions proposées précédemment:

// First, checks if it isn't implemented yet.
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
  };
}

"{0} is dead, but {1} is alive! {0} {2}".format("ASP", "ASP.NET")

sorties

  

ASP est mort, mais ASP.NET est vivant! ASP {2}

Si vous préférez ne pas modifier le prototype de String:

if (!String.format) {
  String.format = function(format) {
    var args = Array.prototype.slice.call(arguments, 1);
    return format.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number] 
        : match
      ;
    });
  };
}

vous donne le bien plus familier:

String.format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');

avec le même résultat:

  

ASP est mort, mais ASP.NET est vivant! ASP {2}

C’est drôle parce que Stack & nbsp; Overflow possède sa propre fonction de formatage pour le prototype String appelé formatUnicorn. Essayez le! Allez dans la console et tapez quelque chose comme:

"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});

Firebug

Vous obtenez cette sortie:

Hello, Gabriel, are you feeling OK?

Vous pouvez utiliser des objets, des tableaux et des chaînes comme arguments! J'ai eu son code et l'ai retravaillé pour produire une nouvelle version de String.prototype.format:

String.prototype.formatUnicorn = String.prototype.formatUnicorn ||
function () {
    "use strict";
    var str = this.toString();
    if (arguments.length) {
        var t = typeof arguments[0];
        var key;
        var args = ("string" === t || "number" === t) ?
            Array.prototype.slice.call(arguments)
            : arguments[0];

        for (key in args) {
            str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);
        }
    }

    return str;
};

Notez l’appel Array.prototype.slice.call(arguments) intelligent - c’est-à-dire que si vous ajoutez des arguments sous forme de chaînes ou de nombres, et non un seul objet de style JSON, vous obtenez le String.Format presque exactement.

"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"

Cela est dû au fait que les Array slice forceront tout ce qui se trouve dans arguments dans un key, que ce soit à l'origine ou non, et le "\\{0\\}" sera l'index (0, 1, 2 .. .) de chaque élément de tableau contraint dans une chaîne (par exemple, " 0 " ;, so <=> pour votre premier motif d'expression rationnelle).

Neat.

Formatage des nombres en JavaScript

Je suis arrivé à cette page de question dans l'espoir de trouver comment formater des nombres en JavaScript, sans introduire une autre bibliothèque. Voici ce que j'ai trouvé:

Arrondissement des nombres en virgule flottante

L'équivalent de sprintf("%.2f", num) dans JavaScript semble être num.toFixed(2), ce qui formate num à 2 décimales, avec arrondi (voir le commentaire de @ ars265 à propos de Math.round ci-dessous).

(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)

Forme exponentielle

L'équivalent de sprintf("%.2e", num) est num.toExponential(2).

(33333).toExponential(2); // "3.33e+4"

Base hexadécimale et autres

Pour imprimer les numéros en base B, essayez num.toString(B). JavaScript prend en charge la conversion automatique vers et depuis les bases 2 à 36 (en outre, certains navigateurs ont prise en charge limitée du codage base64 ).

(3735928559).toString(16); // to base 16: "deadbeef"
parseInt("deadbeef", 16); // from base 16: 3735928559

Pages de référence

Didacticiel rapide sur le formatage des numéros JS

page de référence de Mozilla pour toFixed () (avec liens vers toPrecision (), toExponential (), toLocaleString (), ...)

À partir de ES6, vous pouvez utiliser des chaînes de modèle :

.
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

Sachez que les chaînes de modèles sont entourées de backticks `au lieu de guillemets (simples).

Pour plus d'informations:

https://developers.google.com/web/updates/2015/01 / ES6-Template-Strings

https://developer.mozilla.org/en-US/docs/Web / JavaScript / Référence / template_strings

Remarque: Consultez le site mozilla pour trouver la liste des navigateurs pris en charge.

jsxt, Zippo

Cette option convient mieux.

String.prototype.format = function() {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        var regexp = new RegExp('\\{'+i+'\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[i]);
    }
    return formatted;
};

Avec cette option, je peux remplacer des chaînes comme celles-ci:

'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP');

Avec votre code, le deuxième {0} ne sera pas remplacé. ;)

J'utilise cette fonction simple:

String.prototype.format = function() {
    var formatted = this;
    for( var arg in arguments ) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};

Cela ressemble beaucoup à string.format:

"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")

Pour les utilisateurs de Node.js , il y a util.format qui possède une fonctionnalité semblable à printf:

util.format("%s world", "Hello")

Voici une implémentation minimale de sprintf en JavaScript: cela ne fait que & "% s &"; et "% d " ;, mais j'ai laissé la place à son extension. Cela ne sert à rien pour le PO, mais d’autres personnes qui tombent sur ce fil venant de Google pourraient en tirer profit.

function sprintf() {
    var args = arguments,
    string = args[0],
    i = 1;
    return string.replace(/%((%)|s|d)/g, function (m) {
        // m is the matched format, e.g. %s, %d
        var val = null;
        if (m[2]) {
            val = m[2];
        } else {
            val = args[i];
            // A switch statement so that the formatter can be extended. Default is %s
            switch (m) {
                case '%d':
                    val = parseFloat(val);
                    if (isNaN(val)) {
                        val = 0;
                    }
                    break;
            }
            i++;
        }
        return val;
    });
}

Exemple:

alert(sprintf('Latitude: %s, Longitude: %s, Count: %d', 41.847, -87.661, 'two'));
// Expected output: Latitude: 41.847, Longitude: -87.661, Count: 0

Contrairement aux solutions similaires des réponses précédentes, celle-ci effectue toutes les substitutions en une fois , de sorte qu'elle ne remplacera pas les éléments des valeurs précédemment remplacées.

Je suis surpris que personne n'ait utilisé < code> réduire , il s'agit d'une fonction JavaScript native concise et puissante.

ES6 (EcmaScript2015)

String.prototype.format = function() {
  return [...arguments].reduce((p,c) => p.replace(/%s/,c), this);
};

console.log('Is that a %s or a %s?... No, it\'s %s!'.format('plane', 'bird', 'SOman'));

< ES6

function interpolate(theString, argumentArray) {
    var regex = /%s/;
    var _r=function(p,c){return p.replace(regex,c);}
    return argumentArray.reduce(_r, theString);
}

interpolate("%s, %s and %s", ["Me", "myself", "I"]); // "Me, myself and I"

Comment ça marche:

  

réduire applique une fonction à un accumulateur et à chaque élément du tableau (de gauche à droite) pour le réduire à une valeur unique.

var _r= function(p,c){return p.replace(/%s/,c)};

console.log(
  ["a", "b", "c"].reduce(_r, "[%s], [%s] and [%s]") + '\n',
  [1, 2, 3].reduce(_r, "%s+%s=%s") + '\n',
  ["cool", 1337, "stuff"].reduce(_r, "%s %s %s")
);

Les programmeurs JavaScript peuvent utiliser String.prototype.sprintf à l'adresse https: //github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js . Vous trouverez ci-dessous un exemple:

var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
    d.getHours(), 
    d.getMinutes(), 
    d.getSeconds());

+1 Zippo sauf que le corps de la fonction doit être comme ci-dessous ou sinon il ajoute la chaîne en cours à chaque itération:

String.prototype.format = function() {
    var formatted = this;
    for (var arg in arguments) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};

Ajoutant à la réponse de zippoxer , j'utilise cette fonction:

String.prototype.format = function () {
    var a = this, b;
    for (b in arguments) {
        a = a.replace(/%[a-z]/, arguments[b]);
    }
    return a; // Make chainable
};

var s = 'Hello %s The magic number is %d.';
s.format('world!', 12); // Hello World! The magic number is 12.

J'ai également une version non prototype que j'utilise plus souvent pour sa syntaxe semblable à Java:

function format() {
    var a, b, c;
    a = arguments[0];
    b = [];
    for(c = 1; c < arguments.length; c++){
        b.push(arguments[c]);
    }
    for (c in b) {
        a = a.replace(/%[a-z]/, b[c]);
    }
    return a;
}
format('%d ducks, 55 %s', 12, 'cats'); // 12 ducks, 55 cats

Mise à jour ES 2015

Toutes les nouveautés d’ES 2015 rendent cela beaucoup plus facile:

function format(fmt, ...args){
    return fmt
        .split("%%")
        .reduce((aggregate, chunk, i) =>
            aggregate + chunk + (args[i] || ""), "");
}

format("Hello %%! I ate %% apples today.", "World", 44);
// "Hello World, I ate 44 apples today."

J'ai pensé que, puisque, comme les plus anciens, cela n'analysait pas réellement les lettres, il pourrait tout aussi bien utiliser un seul jeton %% . Cela présente l’avantage d’être évident et de ne pas rendre difficile l’utilisation d’un seul % . Toutefois, si vous avez besoin de %% pour une raison quelconque, vous devez le remplacer par lui-même:

format("I love percentage signs! %%", "%%");
// "I love percentage signs! %%"

Je vais ajouter mes propres découvertes que j'ai découvertes depuis que j'ai demandé:

Malheureusement, il semble que sprintf ne gère pas la mise en forme des milliers de séparateurs comme le format de chaîne de .NET.

J'utilise une petite bibliothèque appelée String.format pour JavaScript qui prend en charge la plupart des formats. capacités de chaîne (y compris le format des nombres et des dates) et utilise la syntaxe .NET. Le script lui-même est inférieur à 4 Ko, il ne génère donc pas beaucoup de temps système.

Très élégant:

String.prototype.format = function (){
    var args = arguments;
    return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (curlyBrack, index) {
        return ((curlyBrack == "{{") ? "{" : ((curlyBrack == "}}") ? "}" : args[index]));
    });
};

// Usage:
"{0}{1}".format("{1}", "{0}")

Le crédit va à (lien brisé) https://gist.github.com/0i0/1519811

Je souhaite partager ma solution pour le "problème". Je n'ai pas réinventé la roue, mais j'essaie de trouver une solution basée sur ce que JavaScript fait déjà. L'avantage est que vous obtenez gratuitement toutes les conversions implicites. La définition de la propriété prototype $ of String donne une syntaxe très jolie et compacte (voir les exemples ci-dessous). Ce n’est peut-être pas le moyen le plus efficace, mais dans la plupart des cas, la sortie n’a pas besoin d’être optimisée.

String.form = function(str, arr) {
    var i = -1;
    function callback(exp, p0, p1, p2, p3, p4) {
        if (exp=='%%') return '%';
        if (arr[++i]===undefined) return undefined;
        exp  = p2 ? parseInt(p2.substr(1)) : undefined;
        var base = p3 ? parseInt(p3.substr(1)) : undefined;
        var val;
        switch (p4) {
            case 's': val = arr[i]; break;
            case 'c': val = arr[i][0]; break;
            case 'f': val = parseFloat(arr[i]).toFixed(exp); break;
            case 'p': val = parseFloat(arr[i]).toPrecision(exp); break;
            case 'e': val = parseFloat(arr[i]).toExponential(exp); break;
            case 'x': val = parseInt(arr[i]).toString(base?base:16); break;
            case 'd': val = parseFloat(parseInt(arr[i], base?base:10).toPrecision(exp)).toFixed(0); break;
        }
        val = typeof(val)=='object' ? JSON.stringify(val) : val.toString(base);
        var sz = parseInt(p1); /* padding size */
        var ch = p1 && p1[0]=='0' ? '0' : ' '; /* isnull? */
        while (val.length<sz) val = p0 !== undefined ? val+ch : ch+val; /* isminus? */
       return val;
    }
    var regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
    return str.replace(regex, callback);
}

String.prototype.$ = function() {
    return String.form(this, Array.prototype.slice.call(arguments));
}

Voici quelques exemples:

String.format("%s %s", [ "This is a string", 11 ])
console.log("%s %s".$("This is a string", 11))
var arr = [ "12.3", 13.6 ]; console.log("Array: %s".$(arr));
var obj = { test:"test", id:12 }; console.log("Object: %s".$(obj));
console.log("%c", "Test");
console.log("%5d".$(12)); // '   12'
console.log("%05d".$(12)); // '00012'
console.log("%-5d".$(12)); // '12   '
console.log("%5.2d".$(123)); // '  120'
console.log("%5.2f".$(1.1)); // ' 1.10'
console.log("%10.2e".$(1.1)); // '   1.10e+0'
console.log("%5.3p".$(1.12345)); // ' 1.12'
console.log("%5x".$(45054)); // ' affe'
console.log("%20#2x".$("45054")); // '    1010111111111110'
console.log("%6#2d".$("111")); // '     7'
console.log("%6#16d".$("affe")); // ' 45054'

Si vous souhaitez gérer le séparateur de milliers, vous devriez vraiment utiliser toLocaleString () à partir de la de date peut formater les dates et heures localisées.

J'ai une solution très proche de celle de Peter, mais elle traite du nombre et de la casse.

if (!String.prototype.format) {
  String.prototype.format = function() {
    var args;
    args = arguments;
    if (args.length === 1 && args[0] !== null && typeof args[0] === 'object') {
      args = args[0];
    }
    return this.replace(/{([^}]*)}/g, function(match, key) {
      return (typeof args[key] !== "undefined" ? args[key] : match);
    });
  };
}

Peut-être serait-il encore mieux de traiter les cas graves, mais pour mes besoins, c'est très bien.

"This is an example from {name}".format({name:"Blaine"});
"This is an example from {0}".format("Blaine");

PS: cette fonction est très pratique si vous utilisez des traductions dans des cadres de modèles tels que AngularJS :

<h1> {{('hello-message'|translate).format(user)}} <h1>
<h1> {{('hello-by-name'|translate).format( user ? user.name : 'You' )}} <h1>

Où le en.json est quelque chose comme

{
    "hello-message": "Hello {name}, welcome.",
    "hello-by-name": "Hello {0}, welcome."
}

Le projet PHPJS a écrit des implémentations JavaScript pour de nombreuses fonctions de PHP. Étant donné que la fonction sprintf () de PHP est fondamentalement identique à la printf () de C, leur implémentation JavaScript devrait répondre à vos besoins.

J'utilise celui-ci:

String.prototype.format = function() {
    var newStr = this, i = 0;
    while (/%s/.test(newStr))
        newStr = newStr.replace("%s", arguments[i++])

    return newStr;
}

Ensuite, je l'appelle:

"<h1>%s</h1><p>%s</p>".format("Header", "Just a test!");

Une version très légèrement différente, celle que je préfère (celle-ci utilise {xxx} jetons au lieu de {0} arguments numérotés, elle est beaucoup plus documentée et convient mieux à la localisation):

String.prototype.format = function(tokens) {
  var formatted = this;
  for (var token in tokens)
    if (tokens.hasOwnProperty(token))
      formatted = formatted.replace(RegExp("{" + token + "}", "g"), tokens[token]);
  return formatted;
};

Une variation serait:

  var formatted = l(this);

qui appelle d'abord une fonction de localisation l ().

Il y a " sprintf " pour JavaScript que vous pouvez trouver à l'adresse http://www.webtoolkit.info/javascript-sprintf.html .

Pour ceux qui aiment Node.JS et son util.format , je viens de l'extraire dans sa forme JavaScript vanille (avec uniquement les fonctions utilisées par util.format):

exports = {};

function isString(arg) {
    return typeof arg === 'string';
}
function isNull(arg) {
    return arg === null;
}
function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
}
function isBoolean(arg) {
    return typeof arg === 'boolean';
}
function isUndefined(arg) {
    return arg === void 0;
}
function stylizeNoColor(str, styleType) {
    return str;
}
function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];

    if (style) {
        return '\u001b[' + inspect.colors[style][0] + 'm' + str +
            '\u001b[' + inspect.colors[style][3] + 'm';
    } else {
        return str;
    }
}
function isFunction(arg) {
    return typeof arg === 'function';
}
function isNumber(arg) {
    return typeof arg === 'number';
}
function isSymbol(arg) {
    return typeof arg === 'symbol';
}
function formatPrimitive(ctx, value) {
    if (isUndefined(value))
        return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
        var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                .replace(/'/g, "\\'")
                .replace(/\\"/g, '"') + '\'';
        return ctx.stylize(simple, 'string');
    }
    if (isNumber(value)) {
        // Format -0 as '-0'. Strict equality won't distinguish 0 from -0,
        // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 .
        if (value === 0 && 1 / value < 0)
            return ctx.stylize('-0', 'number');
        return ctx.stylize('' + value, 'number');
    }
    if (isBoolean(value))
        return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
        return ctx.stylize('null', 'null');
    // es6 symbol primitive
    if (isSymbol(value))
        return ctx.stylize(value.toString(), 'symbol');
}
function arrayToHash(array) {
    var hash = {};

    array.forEach(function (val, idx) {
        hash[val] = true;
    });

    return hash;
}
function objectToString(o) {
    return Object.prototype.toString.call(o);
}
function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
}
function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
}
function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
}
function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
}
function formatPrimitiveNoColor(ctx, value) {
    var stylize = ctx.stylize;
    ctx.stylize = stylizeNoColor;
    var str = formatPrimitive(ctx, value);
    ctx.stylize = stylize;
    return str;
}
function isArray(ar) {
    return Array.isArray(ar);
}
function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || {value: value[key]};
    if (desc.get) {
        if (desc.set) {
            str = ctx.stylize('[Getter/Setter]', 'special');
        } else {
            str = ctx.stylize('[Getter]', 'special');
        }
    } else {
        if (desc.set) {
            str = ctx.stylize('[Setter]', 'special');
        }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
        name = '[' + key + ']';
    }
    if (!str) {
        if (ctx.seen.indexOf(desc.value) < 0) {
            if (isNull(recurseTimes)) {
                str = formatValue(ctx, desc.value, null);
            } else {
                str = formatValue(ctx, desc.value, recurseTimes - 1);
            }
            if (str.indexOf('\n') > -1) {
                if (array) {
                    str = str.split('\n').map(function (line) {
                        return '  ' + line;
                    }).join('\n').substr(2);
                } else {
                    str = '\n' + str.split('\n').map(function (line) {
                        return '   ' + line;
                    }).join('\n');
                }
            }
        } else {
            str = ctx.stylize('[Circular]', 'special');
        }
    }
    if (isUndefined(name)) {
        if (array && key.match(/^\d+$/)) {
            return str;
        }
        name = JSON.stringify('' + key);
        if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
            name = name.substr(1, name.length - 2);
            name = ctx.stylize(name, 'name');
        } else {
            name = name.replace(/'/g, "\\'")
                .replace(/\\"/g, '"')
                .replace(/(^"|"$)/g, "'")
                .replace(/\\\\/g, '\\');
            name = ctx.stylize(name, 'string');
        }
    }

    return name + ': ' + str;
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
        if (hasOwnProperty(value, String(i))) {
            output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
                String(i), true));
        } else {
            output.push('');
        }
    }
    keys.forEach(function (key) {
        if (!key.match(/^\d+$/)) {
            output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
                key, true));
        }
    });
    return output;
}
function reduceToSingleString(output, base, braces) {
    var length = output.reduce(function (prev, cur) {
        return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);

    if (length > 60) {
        return braces[0] +
            (base === '' ? '' : base + '\n ') +
            ' ' +
            output.join(',\n  ') +
            ' ' +
            braces[1];
    }

    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
            // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
            // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
        var ret = value.inspect(recurseTimes, ctx);
        if (!isString(ret)) {
            ret = formatValue(ctx, ret, recurseTimes);
        }
        return ret;
    }

    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
        return primitive;
    }

    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);

    if (ctx.showHidden) {
        keys = Object.getOwnPropertyNames(value);
    }

    // This could be a boxed primitive (new String(), etc.), check valueOf()
    // NOTE: Avoid calling `valueOf` on `Date` instance because it will return
    // a number which, when object has some additional user-stored `keys`,
    // will be printed out.
    var formatted;
    var raw = value;
    try {
        // the .valueOf() call can fail for a multitude of reasons
        if (!isDate(value))
            raw = value.valueOf();
    } catch (e) {
        // ignore...
    }

    if (isString(raw)) {
        // for boxed Strings, we have to remove the 0-n indexed entries,
        // since they just noisey up the output and are redundant
        keys = keys.filter(function (key) {
            return !(key >= 0 && key < raw.length);
        });
    }

    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
        if (isFunction(value)) {
            var name = value.name ? ': ' + value.name : '';
            return ctx.stylize('[Function' + name + ']', 'special');
        }
        if (isRegExp(value)) {
            return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
        }
        if (isDate(value)) {
            return ctx.stylize(Date.prototype.toString.call(value), 'date');
        }
        if (isError(value)) {
            return formatError(value);
        }
        // now check the `raw` value to handle boxed primitives
        if (isString(raw)) {
            formatted = formatPrimitiveNoColor(ctx, raw);
            return ctx.stylize('[String: ' + formatted + ']', 'string');
        }
        if (isNumber(raw)) {
            formatted = formatPrimitiveNoColor(ctx, raw);
            return ctx.stylize('[Number: ' + formatted + ']', 'number');
        }
        if (isBoolean(raw)) {
            formatted = formatPrimitiveNoColor(ctx, raw);
            return ctx.stylize('[Boolean: ' + formatted + ']', 'boolean');
        }
    }

    var base = '', array = false, braces = ['{', '}'];

    // Make Array say that they are Array
    if (isArray(value)) {
        array = true;
        braces = ['[', ']'];
    }

    // Make functions say that they are functions
    if (isFunction(value)) {
        var n = value.name ? ': ' + value.name : '';
        base = ' [Function' + n + ']';
    }

    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
        base = ' ' + RegExp.prototype.toString.call(value);
    }

    // Make dates with properties first say the date
    if (isDate(value)) {
        base = ' ' + Date.prototype.toUTCString.call(value);
    }

    // Make error with message first say the error
    if (isError(value)) {
        base = ' ' + formatError(value);
    }

    // Make boxed primitive Strings look like such
    if (isString(raw)) {
        formatted = formatPrimitiveNoColor(ctx, raw);
        base = ' ' + '[String: ' + formatted + ']';
    }

    // Make boxed primitive Numbers look like such
    if (isNumber(raw)) {
        formatted = formatPrimitiveNoColor(ctx, raw);
        base = ' ' + '[Number: ' + formatted + ']';
    }

    // Make boxed primitive Booleans look like such
    if (isBoolean(raw)) {
        formatted = formatPrimitiveNoColor(ctx, raw);
        base = ' ' + '[Boolean: ' + formatted + ']';
    }

    if (keys.length === 0 && (!array || value.length === 0)) {
        return braces[0] + base + braces[1];
    }

    if (recurseTimes < 0) {
        if (isRegExp(value)) {
            return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
        } else {
            return ctx.stylize('[Object]', 'special');
        }
    }

    ctx.seen.push(value);

    var output;
    if (array) {
        output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
        output = keys.map(function (key) {
            return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
        });
    }

    ctx.seen.pop();

    return reduceToSingleString(output, base, braces);
}
function inspect(obj, opts) {
    // default options
    var ctx = {
        seen: [],
        stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
        // legacy...
        ctx.showHidden = opts;
    } else if (opts) {
        // got an "options" object
        exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;


// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
    'bold': [1, 22],
    'italic': [3, 23],
    'underline': [4, 24],
    'inverse': [7, 27],
    'white': [37, 39],
    'grey': [90, 39],
    'black': [30, 39],
    'blue': [34, 39],
    'cyan': [36, 39],
    'green': [32, 39],
    'magenta': [35, 39],
    'red': [31, 39],
    'yellow': [33, 39]
};

// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'symbol': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
};


var formatRegExp = /%[sdj%]/g;
exports.format = function (f) {
    if (!isString(f)) {
        var objects = [];
        for (var j = 0; j < arguments.length; j++) {
            objects.push(inspect(arguments[j]));
        }
        return objects.join(' ');
    }

    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function (x) {
        if (x === '%%') return '%';
        if (i >= len) return x;
        switch (x) {
            case '%s':
                return String(args[i++]);
            case '%d':
                return Number(args[i++]);
            case '%j':
                try {
                    return JSON.stringify(args[i++]);
                } catch (_) {
                    return '[Circular]';
                }
            default:
                return x;
        }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
        if (isNull(x) || !isObject(x)) {
            str += ' ' + x;
        } else {
            str += ' ' + inspect(x);
        }
    }
    return str;
};

Récolté depuis: https://github.com/joyent/node/blob/master/ lib / util.js

J'ai un formateur légèrement plus long pour JavaScript ici ...

Vous pouvez formater de différentes manières:

  • String.format (entrée, args0, arg1, ...)
  • String.format (entrée, obj)
  • "littéral" .Format (arg0, arg1, ...)
  • "littéral" .format (obj)

De même, si vous avez indiqué un objet ObjectBase.prototype.format (par exemple, avec DateJS ), il utilisera ça.

Exemples ...

var input = "numbered args ({0}-{1}-{2}-{3})";
console.log(String.format(input, "first", 2, new Date()));
//Outputs "numbered args (first-2-Thu May 31 2012...Time)-{3})"

console.log(input.format("first", 2, new Date()));
//Outputs "numbered args(first-2-Thu May 31 2012...Time)-{3})"

console.log(input.format(
    "object properties ({first}-{second}-{third:yyyy-MM-dd}-{fourth})"
    ,{
        'first':'first'
        ,'second':2
        ,'third':new Date() //assumes Date.prototype.format method
    }
));
//Outputs "object properties (first-2-2012-05-31-{3})"

J'ai également créé un alias avec .asFormat et j'ai une détection en place au cas où il existe déjà un string.format (comme avec MS Ajax Toolkit (je déteste cette bibliothèque).

Juste au cas où quelqu'un aurait besoin d'une fonction anti-pollution globale, voici la fonction qui fait la même chose:

  function _format (str, arr) {
    return str.replace(/{(\d+)}/g, function (match, number) {
      return typeof arr[number] != 'undefined' ? arr[number] : match;
    });
  };

Pour le formatage de base:

var template = jQuery.validator.format("{0} is not a valid value");
var result = template("abc");

Je n'ai pas vu la variante String.format :

String.format = function (string) {
    var args = Array.prototype.slice.call(arguments, 1, arguments.length);
    return string.replace(/{(\d+)}/g, function (match, number) {
        return typeof args[number] != "undefined" ? args[number] : match;
    });
};

À utiliser avec les fonctions de réussite jQuery.ajax (). Ne passez qu'un seul argument et remplacez la chaîne par les propriétés de cet objet sous la forme {propertyName}:

String.prototype.format = function () {
    var formatted = this;
    for (var prop in arguments[0]) {
        var regexp = new RegExp('\\{' + prop + '\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[0][prop]);
    }
    return formatted;
};

Exemple:

var userInfo = ("Email: {Email} - Phone: {Phone}").format({ Email: "someone@somewhere.com", Phone: "123-123-1234" });

Avec sprintf.js en place - on peut faire un joli petit format-thingy

String.prototype.format = function(){
    var _args = arguments 
    Array.prototype.unshift.apply(_args,[this])
    return sprintf.apply(undefined,_args)
}   
// this gives you:
"{%1$s}{%2$s}".format("1", "0")
// {1}{0}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top