672

I know in PHP we can do something like this:

$hello = "foo";
$my_string = "I pity the $hello";

Output: "I pity the foo"

I was wondering if this same thing is possible in JavaScript as well. Using variables inside strings without using concatenation — it looks more concise and elegant to write.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
DMin
  • 10,049
  • 10
  • 45
  • 65

17 Answers17

1212

You can take advantage of Template Literals and use this syntax:

`String text ${expression}`

Template literals are enclosed by the back-tick (` `) (grave accent) instead of double or single quotes.

This feature has been introduced in ES2015 (ES6).

Example

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b}.`);
// "Fifteen is 15.

How neat is that?

Bonus:

It also allows for multi-line strings in javascript without escaping, which is great for templates:

return `
    <div class="${foo}">
         ...
    </div>
`;

Browser support:

As this syntax is not supported by older browsers (mostly Internet Explorer), you may want to use Babel/Webpack to transpile your code into ES5 to ensure it will run everywhere.


Side note:

Starting from IE8+ you can use basic string formatting inside console.log:

console.log('%s is %d.', 'Fifteen', 15);
// Fifteen is 15.
bformet
  • 13,465
  • 1
  • 22
  • 25
  • 97
    Don't miss the fact that the template string is delimited with back ticks (\`) instead of your normal quote characters. `"${foo}"` is literally ${foo} `\`${foo}\`` is what you actually want – Hovis Biddle Jun 22 '15 at 17:17
  • 1
    Also there are many transpilers to turn ES6 into ES5 to fixed the compatibility issue! – Nick Oct 06 '15 at 10:14
  • when i change a or b value. console.log(`Fifteen is ${a + b}.`); does not changed dynamically. it always shows Fifteen is 15. – Dharan May 09 '19 at 05:16
  • 4
    Back ticks are a life savior. – MHBN Jul 01 '20 at 12:06
  • But the issue is when I am using this inside a php file then $variable will be considered as php variable and not a js variable as php variable are in format $variable_name. – Allen Johnson Jun 03 '21 at 19:16
177

Prior to Firefox 34 / Chrome 41 / Safari 9 / Microsoft Edge, nope, that was not possible in javascript. You would have to resort to:

var hello = "foo";
var my_string = "I pity the " + hello;
Community
  • 1
  • 1
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
  • 2
    It will soon be possible in javascript (ES6) with Template Strings, see my detailed answer below. – bformet Jan 22 '15 at 12:52
  • [It is possible](http://stackoverflow.com/a/28497562/1189651) if you like to write CoffeeScript, which actually IS javascript with a better syntax. – bformet Feb 13 '15 at 10:37
44

Prior to Firefox 34 / Chrome 41 / Safari 9 / Microsoft Edge, no. Although you could try sprintf for JavaScript to get halfway there:

var hello = "foo";
var my_string = sprintf("I pity the %s", hello);
Community
  • 1
  • 1
Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
  • Thanks. If you're using dojo, sprintf is available as a module: http://bill.dojotoolkit.org/api/1.9/dojox/string/sprintf – user64141 Jul 14 '14 at 16:23
43

well you could do this, but it's not esp general

'I pity the $fool'.replace('$fool', 'fool')

You could easily write a function that does this intelligently if you really needed to

Scott Evernden
  • 39,136
  • 15
  • 78
  • 84
29

Complete and ready to be used answer for <ES6:

 var Strings = {
        create : (function() {
                var regexp = /{([^{]+)}/g;

                return function(str, o) {
                     return str.replace(regexp, function(ignore, key){
                           return (key = o[key]) == null ? '' : key;
                     });
                }
        })()
};

Call as

Strings.create("My firstname is {first}, my last name is {last}", {first:'Neo', last:'Andersson'});

To attach it to String.prototype:

String.prototype.create = function(o) {
           return Strings.create(this, o);
}

Then use as :

"My firstname is ${first}".create({first:'Neo'});

If you are on >ES6 then you can also do:

let first = 'Neo'; 
`My firstname is ${first}`; 
mjs
  • 21,431
  • 31
  • 118
  • 200
12

2022 update: Just use the ES6 Template Literals feature. It's fully supported in practically every browser you'll encounter these days. If you are still targeting browsers like IE11 and lower .. well, my heart goes out to you. The below solution I came up with 5 years ago will still work for you. Also, email me if you want a job that doesn't involve catering to old browsers .

You can use this javascript function to do this sort of templating. No need to include an entire library.

function createStringFromTemplate(template, variables) {
    return template.replace(new RegExp("\{([^\{]+)\}", "g"), function(_unused, varName){
        return variables[varName];
    });
}

createStringFromTemplate(
    "I would like to receive email updates from {list_name} {var1} {var2} {var3}.",
    {
        list_name : "this store",
        var1      : "FOO",
        var2      : "BAR",
        var3      : "BAZ"
    }
);

Output: "I would like to receive email updates from this store FOO BAR BAZ."

Using a function as an argument to the String.replace() function was part of the ECMAScript v3 spec. See this SO answer for more details.

Eric Seastrand
  • 2,473
  • 1
  • 29
  • 36
  • Is this efficient? – mjs Jul 05 '17 at 17:00
  • The efficiency will depend largely on the user's browser, since this solution delegates the "heavy lifting" of matching the regex and doing string replacements to the browser's native functions. In any case, since this is happening on the browser-side anyway, efficiency is not such a huge concern. If you want server-side templating (for Node.JS or the like) you should use the ES6 template literals solution described by @bformet, as it is likely more efficient. – Eric Seastrand Jul 05 '17 at 18:49
9

If you like to write CoffeeScript you could do:

hello = "foo"
my_string = "I pity the #{hello}"

CoffeeScript actually IS javascript, but with a much better syntax.

For an overview of CoffeeScript check this beginner's guide.

bformet
  • 13,465
  • 1
  • 22
  • 25
9

I would use the back-tick ``.

let name1 = 'Geoffrey';
let msg1 = `Hello ${name1}`;
console.log(msg1); // 'Hello Geoffrey'

But if you don't know name1 when you create msg1.

For exemple if msg1 came from an API.

You can use :

let name2 = 'Geoffrey';
let msg2 = 'Hello ${name2}';
console.log(msg2); // 'Hello ${name2}'

const regexp = /\${([^{]+)}/g;
let result = msg2.replace(regexp, function(ignore, key){
    return eval(key);
});
console.log(result); // 'Hello Geoffrey'

It will replace ${name2} with his value.

gturquais
  • 91
  • 1
  • 2
6

I wrote this npm package stringinject https://www.npmjs.com/package/stringinject which allows you to do the following

var string = stringInject("this is a {0} string for {1}", ["test", "stringInject"]);

which will replace the {0} and {1} with the array items and return the following string

"this is a test string for stringInject"

or you could replace placeholders with object keys and values like so:

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

"My username is tjcafferkey on Github" 
codebytom
  • 418
  • 4
  • 12
4

If you're trying to do interpolation for microtemplating, I like Mustache.js for that purpose.

Joe Martinez
  • 854
  • 4
  • 9
4

Don't see any external libraries mentioned here, but Lodash has _.template(),

https://lodash.com/docs/4.17.10#template

If you're already making use of the library it's worth checking out, and if you're not making use of Lodash you can always cherry pick methods from npm npm install lodash.template so you can cut down overhead.

Simplest form -

var compiled = _.template('hello <%= user %>!');
compiled({ 'user': 'fred' });
// => 'hello fred!'

There are a bunch of configuration options also -

_.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
var compiled = _.template('hello {{ user }}!');
compiled({ 'user': 'mustache' });
// => 'hello mustache!'

I found custom delimiters most interesting.

Mark Carpenter Jr
  • 812
  • 1
  • 16
  • 32
3

Simply use:

var util = require('util');

var value = 15;
var s = util.format("The variable value is: %s", value)
Federico Caccia
  • 1,817
  • 1
  • 13
  • 33
0

Create a method similar to String.format() of Java

StringJoin=(s, r=[])=>{
  r.map((v,i)=>{
    s = s.replace('%'+(i+1),v)
  })
return s
}

use

console.log(StringJoin('I can %1 a %2',['create','method'])) //output: 'I can create a method'
0

Peace quote of 2020:

Console.WriteLine("I {0} JavaScript!", ">:D<");

console.log(`I ${'>:D<'} C#`)
MatrixRonny
  • 437
  • 3
  • 11
0

Maybe

wrt=(s, arr=[])=>{
    arr.map((v,i)=>{s = s.replace(/\?/,v);});
    return s;
};
a='first var';
b='secondvar';
tr=wrt('<tr><td>?<td></td>?</td><tr>',[a,b]);
console.log(tr);
//or use tr in html(tr), append(tr) so on and so forth
// Use ? with care in s
Hakan
  • 240
  • 3
  • 4
-1
String.prototype.interpole = function () {
    var c=0, txt=this;
    while (txt.search(/{var}/g) > 0){
        txt = txt.replace(/{var}/, arguments[c]);
        c++;
    }
    return txt;
}

Uso:

var hello = "foo";
var my_string = "I pity the {var}".interpole(hello);
//resultado "I pity the foo"
-5

var hello = "foo";

var my_string ="I pity the";

console.log(my_string, hello)

lalithya
  • 1
  • 2
  • 2
    That doesn't answer the question. You might log out both strings in one line, but that doesn't give you a new string containing both strings, which is what OP is asking for. – Max Vollmer Nov 22 '19 at 19:40