web-dev-qa-db-fra.com

Utilisation de String.Format en JavaScript?

Ça me rend dingue. Je crois avoir posé exactement la même question, mais je ne la retrouve plus (j'ai utilisé la recherche Stack Overflow, la recherche Google, la recherche manuelle dans mes articles et le code).

Je voulais quelque chose qui ressemblerait au C # String.Format où vous pourriez faire quelque chose comme

string format = String.Format("Hi {0}",name);

pour JavaScript, bien sûr, et une personne m'a donné une réponse simple: ce n'était pas un plugin jQuery ou quoi que ce soit, mais je pense que vous avez créé quelque chose en JSON ou quelque chose du genre, et cela a fonctionné et était simple à utiliser.

Moi pour la vie de moi ne peut pas trouver ce post.

J'ai cela dans mon code, mais je n'arrive pas à trouver quoi que ce soit qui l'utilise et je suis presque sûr de l'avoir utilisé plusieurs fois:

String.prototype.format = function(o)
{
    return this.replace(/{([^{}]*)}/g,
       function(a, b)
       {
           var r = o[b];
           return typeof r === 'string' ? r : a;
       }
    );
};
70
chobo2

Adaptez le code à partir de MsAjax string .

Supprimez simplement tout le code _validateParams et vous aurez presque entièrement accès à une classe de chaînes .NET à part entière en JavaScript.

D'accord, j'ai libéré la classe de chaîne msajax, en supprimant toutes les dépendances de msajax. Cela fonctionne très bien, tout comme la classe de chaînes .NET, y compris les fonctions de découpage, endsWith/startsWith, etc.

P.S. - J'ai laissé en place tous les assistants IntelliSense JavaScript et XmlDocs de Visual Studio. Ils sont anodins si vous n'utilisez pas Visual Studio, mais vous pouvez les supprimer si vous le souhaitez.

<script src="script/string.js" type="text/javascript"></script>
<script type="text/javascript">
    var a = String.format("Hello {0}!", "world");
    alert(a);

</script>

String.js

// String.js - liberated from MicrosoftAjax.js on 03/28/10 by Sky Sanders
// permalink: http://stackoverflow.com/a/2534834/2343

/*
    Copyright (c) 2009, CodePlex Foundation
    All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, are permitted
    provided that the following conditions are met:

    *   Redistributions of source code must retain the above copyright notice, this list of conditions
        and the following disclaimer.

    *   Redistributions in binary form must reproduce the above copyright notice, this list of conditions
        and the following disclaimer in the documentation and/or other materials provided with the distribution.

    *   Neither the name of CodePlex Foundation nor the names of its contributors may be used to endorse or
        promote products derived from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
    IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</textarea>
*/

(function(window) {

    $type = String;
    $type.__typeName = 'String';
    $type.__class = true;

    $prototype = $type.prototype;
    $prototype.endsWith = function String$endsWith(suffix) {
        /// <summary>Determines whether the end of this instance matches the specified string.</summary>
        /// <param name="suffix" type="String">A string to compare to.</param>
        /// <returns type="Boolean">true if suffix matches the end of this instance; otherwise, false.</returns>
        return (this.substr(this.length - suffix.length) === suffix);
    }

    $prototype.startsWith = function String$startsWith(prefix) {
        /// <summary >Determines whether the beginning of this instance matches the specified string.</summary>
        /// <param name="prefix" type="String">The String to compare.</param>
        /// <returns type="Boolean">true if prefix matches the beginning of this string; otherwise, false.</returns>
        return (this.substr(0, prefix.length) === prefix);
    }

    $prototype.trim = function String$trim() {
        /// <summary >Removes all leading and trailing white-space characters from the current String object.</summary>
        /// <returns type="String">The string that remains after all white-space characters are removed from the start and end of the current String object.</returns>
        return this.replace(/^\s+|\s+$/g, '');
    }

    $prototype.trimEnd = function String$trimEnd() {
        /// <summary >Removes all trailing white spaces from the current String object.</summary>
        /// <returns type="String">The string that remains after all white-space characters are removed from the end of the current String object.</returns>
        return this.replace(/\s+$/, '');
    }

    $prototype.trimStart = function String$trimStart() {
        /// <summary >Removes all leading white spaces from the current String object.</summary>
        /// <returns type="String">The string that remains after all white-space characters are removed from the start of the current String object.</returns>
        return this.replace(/^\s+/, '');
    }

    $type.format = function String$format(format, args) {
        /// <summary>Replaces the format items in a specified String with the text equivalents of the values of   corresponding object instances. The invariant culture will be used to format dates and numbers.</summary>
        /// <param name="format" type="String">A format string.</param>
        /// <param name="args" parameterArray="true" mayBeNull="true">The objects to format.</param>
        /// <returns type="String">A copy of format in which the format items have been replaced by the   string equivalent of the corresponding instances of object arguments.</returns>
        return String._toFormattedString(false, arguments);
    }

    $type._toFormattedString = function String$_toFormattedString(useLocale, args) {
        var result = '';
        var format = args[0];

        for (var i = 0; ; ) {
            // Find the next opening or closing brace
            var open = format.indexOf('{', i);
            var close = format.indexOf('}', i);
            if ((open < 0) && (close < 0)) {
                // Not found: copy the end of the string and break
                result += format.slice(i);
                break;
            }
            if ((close > 0) && ((close < open) || (open < 0))) {

                if (format.charAt(close + 1) !== '}') {
                    throw new Error('format stringFormatBraceMismatch');
                }

                result += format.slice(i, close + 1);
                i = close + 2;
                continue;
            }

            // Copy the string before the brace
            result += format.slice(i, open);
            i = open + 1;

            // Check for double braces (which display as one and are not arguments)
            if (format.charAt(i) === '{') {
                result += '{';
                i++;
                continue;
            }

            if (close < 0) throw new Error('format stringFormatBraceMismatch');


            // Find the closing brace

            // Get the string between the braces, and split it around the ':' (if any)
            var brace = format.substring(i, close);
            var colonIndex = brace.indexOf(':');
            var argNumber = parseInt((colonIndex < 0) ? brace : brace.substring(0, colonIndex), 10) + 1;

            if (isNaN(argNumber)) throw new Error('format stringFormatInvalid');

            var argFormat = (colonIndex < 0) ? '' : brace.substring(colonIndex + 1);

            var arg = args[argNumber];
            if (typeof (arg) === "undefined" || arg === null) {
                arg = '';
            }

            // If it has a toFormattedString method, call it.  Otherwise, call toString()
            if (arg.toFormattedString) {
                result += arg.toFormattedString(argFormat);
            }
            else if (useLocale && arg.localeFormat) {
                result += arg.localeFormat(argFormat);
            }
            else if (arg.format) {
                result += arg.format(argFormat);
            }
            else
                result += arg.toString();

            i = close + 1;
        }

        return result;
    }

})(window);
68
Sky Sanders

Voici ce que j'utilise. J'ai cette fonction définie dans un fichier d'utilitaire: 

  String.format = function() {
      var s = arguments[0];
      for (var i = 0; i < arguments.length - 1; i++) {       
          var reg = new RegExp("\\{" + i + "\\}", "gm");             
          s = s.replace(reg, arguments[i + 1]);
      }
      return s;
  }

Et j'appelle ça comme ça:

var greeting = String.format("Hi, {0}", name);

Je ne me rappelle pas où j'ai trouvé cela, mais cela m'a été très utile. J'aime ça parce que la syntaxe est la même que celle de la version C #.

42
Jeremy

Vous pouvez faire des séries de remplacements comme ça:

function format(str)
{
    for(i = 1; i < arguments.length; i++)
    {
        str = str.replace('{' + (i - 1) + '}', arguments[i]);
    }
    return str;
}

Une meilleure approche consistera à utiliser le paramètre de remplacement par la fonction:

function format(str, obj) {
    return str.replace(/\{\s*([^}\s]+)\s*\}/g, function(m, p1, offset, string) {
        return obj[p1]
    })
}

De cette façon, vous pouvez fournir à la fois des index et des paramètres nommés:

var arr = ['0000', '1111', '2222']

arr.a = 'aaaa'

str = format(" { 0 } , {1}, { 2}, {a}", arr)
// returns 0000 , 1111, 2222, aaaa
20
vittore

Voici une fonction de formatage de chaîne utile utilisant des expressions régulières et des captures:

function format (fmtstr) {
  var args = Array.prototype.slice.call(arguments, 1);
  return fmtstr.replace(/\{(\d+)\}/g, function (match, index) {
    return args[index];
  });
}

Les chaînes peuvent être formatées comme C # String.Format:

var str = format('{0}, {1}!', 'Hello', 'world');
console.log(str); // prints "Hello, world!"

le format placera la bonne variable au bon endroit, même si elle semble hors d'usage:

var str = format('{1}, {0}!', 'Hello', 'world');
console.log(str); // prints "world, Hello!"

J'espère que cela t'aides!

12
pje

Sans fonction tierce: 

string format = "Hi {0}".replace('{0}', name)

Avec plusieurs paramètres:

string format = "Hi {0} {1}".replace('{0}', name).replace('{1}', lastname)
10
Dustin Laine

La méthode String.Format de .NET Framework a plusieurs signatures . Celui que j’aime bien the most utilise params dans son prototype,

public static string Format(
    string format,
    params Object[] args
)

En utilisant cette version, vous pouvez non seulement lui transmettre un nombre variable d'arguments, mais également un argument de tableau. 

Parce que j'aime la solution simple proposée par Jeremy, j'aimerais l'étendre un peu:

var StringHelpers = {
    format: function(format, args) {
        var i;
        if (args instanceof Array) {
            for (i = 0; i < args.length; i++) {
                format = format.replace(new RegExp('\\{' + i + '\\}', 'gm'), args[i]);
            }
            return format;
        }
        for (i = 0; i < arguments.length - 1; i++) {
            format = format.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i + 1]);
        }
        return format;
    }
};

Vous pouvez maintenant utiliser votre version JavaScript de String.Format de la manière suivante:

StringHelpers.format("{0}{1}", "a", "b")

et 

StringHelpers.format("{0}{1}", ["a", "b"])
3
jwaliszko

Utilisez un modèle littéral dans ECMAScript 6:

var customer = { name: "Foo" }
var card = { amount: 7, product: "Bar", unitprice: 42 }
var message = `Hello ${customer.name},
               want to buy ${card.amount} ${card.product} for
               a total of ${card.amount * card.unitprice} bucks?`
2
gavin

Basé sur la réponse de @ roydukkey, un peu plus optimisé pour l'exécution (il met en cache les expressions rationnelles):

(function () {
    if (!String.prototype.format) {
        var regexes = {};
        String.prototype.format = function (parameters) {
            for (var formatMessage = this, args = arguments, i = args.length; --i >= 0;)
                formatMessage = formatMessage.replace(regexes[i] || (regexes[i] = RegExp("\\{" + (i) + "\\}", "gm")), args[i]);
            return formatMessage;
        };
        if (!String.format) {
            String.format = function (formatMessage, params) {
                for (var args = arguments, i = args.length; --i;)
                    formatMessage = formatMessage.replace(regexes[i - 1] || (regexes[i - 1] = RegExp("\\{" + (i - 1) + "\\}", "gm")), args[i]);
                return formatMessage;
            };
        }
    }
})();
2
Adaptabi

Voici une solution qui fonctionne simplement avec String.prototype:

String.prototype.format = function() {
    var s = this;
    for (var i = 0; i < arguments.length; i++) {       
        var reg = new RegExp("\\{" + i + "\\}", "gm");             
        s = s.replace(reg, arguments[i]);
    }
    return s;
}
2
Jonathan

Il suffit de créer et d’utiliser cette fonction:

function format(str, args) {
   for (i = 0; i < args.length; i++)
      str = str.replace("{" + i + "}", args[i]);
   return str;
}

Si vous ne souhaitez pas modifier le paramètre str , alors, avant la boucle for, clonez-le (dupliquez-le) dans une nouvelle chaîne (créez une nouvelle copie de str ), puis définissez la copie dans le répertoire. for loop et le renvoie enfin à la place du paramètre lui-même.

En C # (Sharp), il est simple de créer une copie en appelant simplement String.Clone(), mais je ne sais pas comment utiliser JavaScript, mais vous pouvez effectuer une recherche sur Google ou surfer sur Internet et apprendre comment le faire.

Je viens de vous donner mon idée du format de chaîne en JavaScript.

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

Usage:

'{0}-{1}'.format('a','b');
// Result: 'a-b'

JSFiddle

1
Mikael Engver

Je viens de commencer à porter la String.format() de Java en JavaScript. Vous pourriez trouver cela utile aussi. 

Il supporte des choses basiques comme ceci:

StringFormat.format("Hi %s, I like %s", ["Rob", "icecream"]);

Ce qui résulte en 

Hi Rob, I like icecream.

Mais aussi un formatage numérique et un format de date plus avancés comme: 

StringFormat.format("Duke's Birthday: %1$tA %1$te %1$tB, %1$tY", [new Date("2014-12-16")]);

Duke's Birthday: Tuesday 16 December, 2014

Voir pour plus dans les exemples.

Voir ici: https://github.com/RobAu/javascript.string.format

1
RobAu

Voici une solution qui permet à la fois des options de prototype et de fonction.

// --------------------------------------------------------------------
// Add prototype for 'String.format' which is c# equivalent
//
// String.format("{0} i{2}a night{1}", "This", "mare", "s ");
// "{0} i{2}a night{1}".format("This", "mare", "s ");
// --------------------------------------------------------------------

if(!String.format)
    String.format = function(){
        for (var i = 0, args = arguments; i < args.length - 1; i++)
            args[0] = args[0].replace("{" + i + "}", args[i + 1]);
        return args[0];
    };
if(!String.prototype.format && String.format)
    String.prototype.format = function(){
        var args = Array.prototype.slice.call(arguments).reverse();
        args.Push(this);
        return String.format.apply(this, args.reverse())
    };

Prendre plaisir.

1
roydukkey
//Add "format" method to the string class
//supports:  "Welcome {0}. You are the first person named {0}".format("David");
//       and "First Name:{} Last name:{}".format("David","Wazy");
//       and "Value:{} size:{0} shape:{1} weight:{}".format(value, size, shape, weight)
String.prototype.format = function () {
    var content = this;
    for (var i = 0; i < arguments.length; i++) {
        var target = '{' + i + '}';
        content=content.split(target).join(String(arguments[i]))
        content = content.replace("{}", String(arguments[i]));
    }
    return content;
}
alert("I {} this is what {2} want and {} works for {2}!".format("hope","it","you"))

Vous pouvez mélanger et assortir des emplacements de remplacement de position et "nommés" en utilisant cette fonction.

1
davidWazy

Hormis le fait que vous modifiez le prototype String, la fonction que vous avez fournie n’est pas fausse. La façon dont vous l'utiliseriez est la suivante:

"Hello {0},".format(["Bob"]);

Si vous le voulez en tant que fonction autonome, vous pouvez le modifier légèrement comme suit:

function format(string, object) {
    return string.replace(/{([^{}]*)}/g,
       function(match, group_match)
       {
           var data = object[group_match];
           return typeof data === 'string' ? data : match;
       }
    );
}

La méthode de Vittore est également bonne. Sa fonction est appelée, chaque option de formatage supplémentaire étant transmise en tant qu’argument, alors que la vôtre attend un objet.

Cela ressemble en réalité au moteur micro-templates de John Resig.

1
Sean Vieira

Voici mes deux cents :

function stringFormat(str) {
  if (str !== undefined && str !== null) {
    str = String(str);
    if (str.trim() !== "") {
      var args = arguments;
      return str.replace(/(\{[^}]+\})/g, function(match) {
        var n = +match.slice(1, -1);
        if (n >= 0 && n < args.length - 1) {
          var a = args[n + 1];
          return (a !== undefined && a !== null) ? String(a) : "";
        }
        return match;
      });
    }
  }
  return "";
}

alert(stringFormat("{1}, {0}. You're looking {2} today.",
  "Dave", "Hello", Math.random() > 0.5 ? "well" : "good"));
1
jramos

Votre fonction prend déjà un objet JSON en tant que paramètre:

string format = "Hi {foo}".replace({
    "foo": "bar",
    "fizz": "buzz"
});

si vous remarquez, le code:

var r = o[b];

examine votre paramètre (o) et utilise une paire clé-valeur à l'intérieur pour résoudre le

1
David
String.prototype.format = function () {
    var formatted = this;
    for (var arg in arguments) {
        formatted = formatted.split('{' + arg + '}').join(arguments[arg]);
    }
    return formatted;
};

USAGE:

'Hello {0}!'.format('Word')->Hello World!

'He{0}{0}o World!'.format('l')->Hello World!

'{0} {1}!'.format('Hello', 'Word')->Hello World!

'{0}!'.format('Hello {1}', 'Word')->Hello World!

0
Cyrus

Utilisez sprintf library

Ici vous avez un link où vous pouvez trouver les fonctionnalités de cette bibliothèque.

0
Alfredo A.