[javascript] Equivalent of String.format in jQuery

I'm trying to move some JavaScript code from MicrosoftAjax to JQuery. I use the JavaScript equivalents in MicrosoftAjax of the popular .net methods, e.g. String.format(), String.startsWith(), etc. Are there equivalents to them in jQuery?

This question is related to javascript jquery string.format

The answer is


This is a faster/simpler (and prototypical) variation of the function that Josh posted:

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) 

I use this so much that I aliased it to just f, but you can also use the more verbose format. e.g. 'Hello {0}!'.format(name)


There is an (somewhat) official option: jQuery.validator.format.

Comes with jQuery Validation Plugin 1.6 (at least).
Quite similar to the String.Format found in .NET.

Edit Fixed broken link.


I couldn't get Josh Stodola's answer to work, but the following worked for me. Note the specification of prototype. (Tested on IE, FF, Chrome, and 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 really should be a clone of this so as not to be a destructive method, but it's not really necessary.


I have a plunker that adds it to the string prototype: string.format It is not just as short as some of the other examples, but a lot more flexible.

Usage is similar to c# version:

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

Also, added support for using names & object properties

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

Expanding on adamJLev's great answer above, here is the TypeScript version:

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

This violates DRY principle, but it's a concise solution:

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

Here's my version that is able to escape '{', and clean up those unassigned place holders.

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

Now you can use Template Literals:

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


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

None of the answers presented so far has no obvious optimization of using enclosure to initialize once and store regular expressions, for subsequent usages.

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

Also, none of the examples respects format() implementation if one already exists.


If you're using the validation plugin you can use:

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

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


You can also closure array with replacements like this.

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

or you can try bind

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

Many of the above functions (except Julian Jelfs's) contain the following error:

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

Or, for the variants that count backwards from the end of the argument list:

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

Here's a correct function. It's a prototypal variant of Julian Jelfs's code, which I made a bit tighter:

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

And here is a slightly more advanced version of the same, which allows you to escape braces by doubling them:

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

This works correctly:

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

Here is another good implementation by Blair Mitchelmore, with a bunch of nice extra features: https://web.archive.org/web/20120315214858/http://blairmitchelmore.com/javascript/string.format


Though not exactly what the Q was asking for, I've built one that is similar but uses named placeholders instead of numbered. I personally prefer having named arguments and just send in an object as an argument to it (more verbose, but easier to maintain).

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

Here's an example usage...

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

Way past the late season but I've just been looking at the answers given and have my tuppence worth:

Usage:

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

Method:

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

Result:

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

Here's mine:

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

Not bullet proof but works if you use it sensibly.


Using a modern browser, which supports EcmaScript 2015 (ES6), you can enjoy Template Strings. Instead of formatting, you can directly inject the variable value into it:

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

Note the template string has to be written using back-ticks (`).


The following answer is probably the most efficient but has the caveat of only being suitable for 1 to 1 mappings of arguments. This uses the fastest way of concatenating strings (similar to a stringbuilder: array of strings, joined). This is my own code. Probably needs a better separator though.

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

Use it like:

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

Made a format function that takes either a collection or an array as arguments

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