web-dev-qa-db-fra.com

Équivalent de String.format dans jQuery

J'essaie de déplacer du code JavaScript de MicrosoftAjax vers JQuery. J'utilise les équivalents JavaScript dans MicrosoftAjax des méthodes .net populaires, par exemple. String.format (), String.startsWith (), etc. Y a-t-il des équivalents dans jQuery?

188
Waleed Eissa

Le code source pour ASP.NET AJAX est disponible à titre de référence. Vous pouvez donc le sélectionner et inclure les parties que vous souhaitez continuer à utiliser dans un fichier JS distinct. Ou, vous pouvez les porter sur jQuery.

Voici la fonction de formatage ...

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 voici les finsAvec et commenceAvec fonctions prototypes ...

String.prototype.endsWith = function (suffix) {
  return (this.substr(this.length - suffix.length) === suffix);
}

String.prototype.startsWith = function(prefix) {
  return (this.substr(0, prefix.length) === prefix);
}
190
Josh Stodola

Il s’agit d’une variante plus rapide/plus simple (et prototypique) de la fonction que Josh a publiée:

String.prototype.format = String.prototype.f = function() {
    var s = this,
        i = arguments.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    }
    return s;
};

Usage:

'Added {0} by {1} to your collection'.f(title, artist)
'Your balance is {0} USD'.f(77.7) 

J'utilise tellement cela que je l'ai associé à juste f, mais vous pouvez aussi utiliser le plus verbeux format. par exemple. 'Hello {0}!'.format(name)

145
adamJLev

La plupart des fonctions ci-dessus (sauf celles de Julian Jelfs) contiennent l'erreur suivante:

js> '{0} {0} {1} {2}'.format(3.14, 'a{2}bc', 'foo');
3.14 3.14 afoobc foo

Ou, pour les variantes qui comptent à partir de la fin de la liste d'arguments:

js> '{0} {0} {1} {2}'.format(3.14, 'a{0}bc', 'foo');
3.14 3.14 a3.14bc foo

Voici une fonction correcte. C'est une variante prototype du code de Julian Jelfs, que j'ai un peu plus serré:

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{(\d+)\}/g, function (m, n) { return args[n]; });
};

Et voici une version légèrement plus avancée de la même chose, qui vous permet d'échapper aux accolades en les doublant:

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
    if (m == "{{") { return "{"; }
    if (m == "}}") { return "}"; }
    return args[n];
  });
};

Cela fonctionne correctement:

js> '{0} {{0}} {{{0}}} {1} {2}'.format(3.14, 'a{2}bc', 'foo');
3.14 {0} {3.14} a{2}bc foo

Voici une autre bonne implémentation de Blair Mitchelmore, avec un tas de fonctionnalités supplémentaires intéressantes: https://web.archive.org/web/20120315214858/http://blairmitchelmore.com/javascript/string.format

130
gpvos

Création d'une fonction de formatage prenant comme argument une collection ou un tableau

Usage: 

format("i can speak {language} since i was {age}",{language:'javascript',age:10});

format("i can speak {0} since i was {1}",'javascript',10});

Code:

var format = function (str, col) {
    col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);

    return str.replace(/\{\{|\}\}|\{(\w+)\}/g, function (m, n) {
        if (m == "{{") { return "{"; }
        if (m == "}}") { return "}"; }
        return col[n];
    });
};
47
ianj

Il existe une option (un peu) officielle: jQuery.validator.format .

Livré avec jQuery Validation Plugin 1.6 (au moins).
Assez similaire au String.Format trouvé dans .NET.

Edit Correction du lien cassé.

36
rsenna

Si vous utilisez le plugin de validation, vous pouvez utiliser:

jQuery.validator.format("{0} {1}", "cool", "formatting") = 'cool formatting'

http://docs.jquery.com/Plugins/Validation/jQuery.validator.format#templateargumentargumentN ...

17
fiestacasey

Bien que ce ne soit pas exactement ce que demandait le Q, j’en ai construit un similaire, qui utilise des espaces réservés nommés au lieu de numérotés. Personnellement, je préfère avoir des arguments nommés et simplement envoyer un objet comme argument (plus détaillé, mais plus facile à gérer).

String.prototype.format = function (args) {
    var newStr = this;
    for (var key in args) {
        newStr = newStr.replace('{' + key + '}', args[key]);
    }
    return newStr;
}

Voici un exemple d'utilisation ...

alert("Hello {name}".format({ name: 'World' }));
12
Brian

À l'aide d'un navigateur moderne prenant en charge EcmaScript 2015 (ES6), vous pouvez profiter de Template Strings. Au lieu de formater, vous pouvez directement y injecter la valeur de la variable:

var name = "Waleed";
var message = `Hello ${name}!`;

Notez que la chaîne de modèle doit être écrite en utilisant les ticks arrière (`).

6
david

Aucune des réponses présentées à ce jour n’a montré d’optimisation évidente de l’utilisation de Enclosure pour initialiser une fois et stocker des expressions régulières, pour des utilisations ultérieures.

// DBJ.ORG string.format function
// usage:   "{0} means 'zero'".format("nula") 
// returns: "nula means 'zero'"
// place holders must be in a range 0-99.
// if no argument given for the placeholder, 
// no replacement will be done, so
// "oops {99}".format("!")
// returns the input
// same placeholders will be all replaced 
// with the same argument :
// "oops {0}{0}".format("!","?")
// returns "oops !!"
//
if ("function" != typeof "".format) 
// add format() if one does not exist already
  String.prototype.format = (function() {
    var rx1 = /\{(\d|\d\d)\}/g, rx2 = /\d+/ ;
    return function() {
        var args = arguments;
        return this.replace(rx1, function($0) {
            var idx = 1 * $0.match(rx2)[0];
            return args[idx] !== undefined ? args[idx] : (args[idx] === "" ? "" : $0);
        });
    }
}());

alert("{0},{0},{{0}}!".format("{X}"));

En outre, aucun des exemples ne respecte l'implémentation de format () s'il en existe déjà un.

6
user182669

Voilà le mien:

String.format = function(tokenised){
        var args = arguments;
        return tokenised.replace(/{[0-9]}/g, function(matched){
            matched = matched.replace(/[{}]/g, "");
            return args[parseInt(matched)+1];             
        });
    }

Pas à l'épreuve des balles mais fonctionne si vous l'utilisez judicieusement. 

4
Julian Jelfs

Bien au-delà de la fin de saison, mais je viens juste de regarder les réponses données et ça vaut la peine:

Usage:

var one = strFormat('"{0}" is not {1}', 'aalert', 'defined');
var two = strFormat('{0} {0} {1} {2}', 3.14, 'a{2}bc', 'foo');

Méthode:

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

Résultat:

"aalert" is not defined
3.14 3.14 a{2}bc foo
3
RickL

Vous pouvez maintenant utiliser Littéraux de modèle

var w = "the Word";
var num1 = 2;
var num2 = 3;

var long_multiline_string = `This is very long
multiline templete string. Putting somthing here:
${w}
I can even use expresion interpolation:
Two add three = ${num1 + num2}
or use Tagged template literals
You need to enclose string with the back-tick (\` \`)`;

console.log(long_multiline_string);

3
Arek Kostrzeba

La réponse suivante est probablement la plus efficace, mais présente l’avertissement de ne convenir qu’à 1 mappage d’arguments. Ceci utilise le moyen le plus rapide de concaténer des chaînes (similaire à un constructeur de chaînes: tableau de chaînes jointes). Ceci est mon propre code. Cela nécessite probablement un meilleur séparateur.

String.format = function(str, args)
{
    var t = str.split('~');
    var sb = [t[0]];
    for(var i = 0; i < args.length; i++){
        sb.Push(args[i]);
        sb.Push(t[i+1]);
    }
    return sb.join("");
}

Utilisez-le comme:

alert(String.format("<a href='~'>~</a>", ["one", "two"]));
2
Skychan

Voici ma version qui est capable d'échapper à '{' et de nettoyer ces espaces réservés non attribués.

function getStringFormatPlaceHolderRegEx(placeHolderIndex) {
    return new RegExp('({)?\\{' + placeHolderIndex + '\\}(?!})', 'gm')
}

function cleanStringFormatResult(txt) {
    if (txt == null) return "";

    return txt.replace(getStringFormatPlaceHolderRegEx("\\d+"), "");
}

String.prototype.format = function () {
    var txt = this.toString();
    for (var i = 0; i < arguments.length; i++) {
        var exp = getStringFormatPlaceHolderRegEx(i);
        txt = txt.replace(exp, (arguments[i] == null ? "" : arguments[i]));
    }
    return cleanStringFormatResult(txt);
}
String.format = function () {
    var s = arguments[0];
    if (s == null) return "";

    for (var i = 0; i < arguments.length - 1; i++) {
        var reg = getStringFormatPlaceHolderRegEx(i);
        s = s.replace(reg, (arguments[i + 1] == null ? "" : arguments[i + 1]));
    }
    return cleanStringFormatResult(s);
}
2
Feng

Ceci viole le principe DRY, mais c'est une solution concise:

var button = '<a href="{link}" class="btn">{text}</a>';
button = button.replace('{text}','Authorize on GitHub').replace('{link}', authorizeUrl);
1
TheNamelessOne

J'ai un plunker qui l'ajoute au prototype de chaîne: string.format Il n'est pas aussi court que certains autres exemples, mais beaucoup plus flexible.

L'utilisation est similaire à la version c #:

var str2 = "Meet you on {0}, ask for {1}";
var result2 = str2.format("Friday", "Suzy"); 
//result: Meet you on Friday, ask for Suzy
//NB: also accepts an array

Ajout du support pour l'utilisation des noms et des propriétés d'objet

var str1 = "Meet you on {day}, ask for {Person}";
var result1 = str1.format({day: "Thursday", person: "Frank"}); 
//result: Meet you on Thursday, ask for Frank
0
ShrapNull
<html>
<body>
<script type="text/javascript">
   var str="http://xyz.html?ID={0}&TId={1}&STId={2}&RId={3},14,480,3,38";
   document.write(FormatString(str));
   function FormatString(str) {
      var args = str.split(',');
      for (var i = 0; i < args.length; i++) {
         var reg = new RegExp("\\{" + i + "\\}", "");             
         args[0]=args[0].replace(reg, args [i+1]);
      }
      return args[0];
   }
</script>
</body>
</html>
0
Kishor Dalwadi

En développant l'excellente réponse d'adamJLev ci-dessus , voici la version TypeScript:

// Extending String prototype
interface String {
    format(...params: any[]): string;
}

// Variable number of params, mimicking C# params keyword
// params type is set to any so consumer can pass number
// or string, might be a better way to constraint types to
// string and number only using generic?
String.prototype.format = function (...params: any[]) {
    var s = this,
        i = params.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), params[i]);
    }

    return s;
};
0
Annie

Je ne pouvais pas obtenir la réponse de Josh Stodola au travail, mais ce qui suit a fonctionné pour moi. Notez la spécification de prototype. (Testé sur IE, FF, Chrome et Safari.):

String.prototype.format = function() {
    var s = this;
    if(t.length - 1 != args.length){
        alert("String.format(): Incorrect number of arguments");
    }
    for (var i = 0; i < arguments.length; i++) {       
        var reg = new RegExp("\\{" + i + "\\}", "gm");
        s = s.replace(reg, arguments[i]);
    }
    return s;
}

s devrait vraiment être un clone of this afin de ne pas être une méthode destructive, mais ce n'est pas vraiment nécessaire.

0
JellicleCat

Vous pouvez également fermer tableau avec des remplacements comme celui-ci. 

var url = '/getElement/_/_/_'.replace(/_/g, (_ => this.ar[this.i++]).bind({ar: ["invoice", "id", 1337],i: 0}))
> '/getElement/invoice/id/1337

ou vous pouvez essayer bind

'/getElement/_/_/_'.replace(/_/g, (function(_) {return this.ar[this.i++];}).bind({ar: ["invoice", "id", 1337],i: 0}))
0
test30