Videos
Hi, I'm new-ish to web dev, by way of web design, by way of graphic design, so I have a lot to learn. I think maybe I'm missing something re template literals. consider:
return '<h1>Hello ' + firstName + ', welcome to your account.</h1>';
and
return `<h1>Hello '${ firstName }', welcome to your account.</h1>`;Ok, so you're typing 1 less char, is that the only benefit? Are there performance benefits? It's certainly not significantly more legible or anything. What's the use case where template literals are just far and away superior to plain old string concat?
EDIT: Thanks everyone, I feel like I know when and how to use template literals now.
Hello ${firstName}, welcome to your account.
; -- so it is a little easier to write and read. Opening and closing your strings a bunch of times can get tiresome. Also you can have any number of line breaks inside a template literal, which is a heck of a lot easier than having to close your string and add a + on every new line if you're using string concatenation on a big block of HTML. But point taken, string concatenation still works just fine if you prefer it. And it works on all browsers, which isn't true for template literals, so that's good too.If you are using template literals only with placeholders (e.g. `Hello ${person.name}`) like in the question's example, then the result is the same as just concatenating strings. Subjectively it looks better and is easier to read, especially for multi-line strings or strings containing both ' and " since you don't have to escape those characters any more.
Readability is a great feature, but the most interesting thing about templates are Tagged template literals:
let person = {name: 'John Smith'};
let tag = (strArr, name) => strArr[0] + name.toUpperCase() + strArr[1];
tag `My name is ${person.name}!` // Output: My name is JOHN SMITH!
In the third line of this example, a function named tag is called. The content of the template string is split into multiple variables, that you can access in the arguments of the tag function: literal sections (in this example the value of strArr[0] is My name is and the value of strArr[1] is !) and substitutions (John Smith). The template literal will be evaluated to whatever the tag function returns.
The ECMAScript wiki lists some possible use cases, like automatically escaping or encoding input, or localization. You could create a tag function named msg that looks up the literal parts like My name is and substitutes them with translations into the current locale's language, for example into German:
console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.
The value returned by the tag function doesn't even have to be a string. You could create a tag function named $ which evaluates the string and uses it as a query selector to return a collection of DOM nodes, like in this example:
{className}[href=~'//${domain}/']`
ES6 comes up with a new type of string literal, using the ` back-tick as the delimiter. These literals do allow basic string interpolation expressions to be embedded, which are then automatically parsed and evaluated.
let actor = {name: 'RajiniKanth', age: 68};
let oldWayStr = "<p>My name is " + actor.name + ",</p>\n" +
"<p>I am " + actor.age + " old</p>\n";
let newWayHtmlStr =
`<p>My name is ${actor.name},</p>
<p>I am ${actor.age} old</p>`;
console.log(oldWayStr);
console.log(newWayHtmlStr);
As you can see, we used the ..`` around a series of characters, which are interpreted as a string literal, but any expressions of the form ${..} are parsed and evaluated inline immediately.
One really nice benefit of interpolated string literals is they are allowed to split across multiple lines:
var Actor = {"name" : "RajiniKanth"};
var text =
`Now is the time for all good men like ${Actor.name}
to come to the aid of their
country!`;
console.log( text );
// Now is the time for all good men
// to come to the aid of their
// country!
Interpolated Expressions
Any valid expression is allowed to appear inside ${..} in an interpolated string lit‐ eral, including function calls, inline function expression calls, and even other interpo‐ lated string literals!
function upper(s) {
return s.toUpperCase();
}
var who = "reader"
var text =
`A very ${upper( "warm" )} welcome
to all of you ${upper( `${who}s` )}!`;
console.log( text );
// A very WARM welcome
// to all of you READERS!
Here, the inner ${who}s`` interpolated string literal was a little bit nicer convenience for us when combining the who variable with the "s" string, as opposed to who + "s". Also to keep an note is an interpolated string literal is just lexically scoped where it appears, not dynamically scoped in any way:
function foo(str) {
var name = "foo";
console.log( str );
}
function bar() {
var name = "bar";
foo( `Hello from ${name}!` );
}
var name = "global";
bar(); // "Hello from bar!"
Using the template literal for the HTML is definitely more readable by reducing the annoyance.
The plain old way:
'<div class="' + className + '">' +
'<p>' + content + '</p>' +
'<a href="' + link + '">Let\'s go</a>'
'</div>';
With ES6:
`<div class="${className}">
<p>${content}</p>
<a href="${link}">Let's go</a>
</div>`
- Your string can span multiple lines.
- You don't have to escape quotation characters.
- You can avoid groupings like: '">'
- You don't have to use the plus operator.
Tagged Template Literals
We can also tag a template string, when a template string is tagged, the literals and substitutions are passed to function which returns the resulting value.
function myTaggedLiteral(strings) {
console.log(strings);
}
myTaggedLiteral`test`; //["test"]
function myTaggedLiteral(strings,value,value2) {
console.log(strings,value, value2);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
// ["test ", " ", ""]
// "Neat"
// 5
We can use the spread operator here to pass multiple values. The first argument — we called it strings — is an array of all the plain strings (the stuff between any interpolated expressions).
we then gather up all subsequent arguments into an array called values using the ... gather/rest operator, though you could of course have left them as individual named parameters following the strings parameter like we did above (value1, value2 etc).
function myTaggedLiteral(strings,...values) {
console.log(strings);
console.log(values);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
// ["test ", " ", ""]
// ["Neat", 5]
The argument(s) gathered into our values array are the results of the already evaluated interpolation expressions found in the string literal. A tagged string literal is like a processing step after the interpolations are evaluated but before the final string value is compiled, allowing you more control over generating the string from the literal. Let's look at an example of creating a re-usable templates.
const Actor = {
name: "RajiniKanth",
store: "Landmark"
}
const ActorTemplate = templater`<article>
<h3>${'name'} is a Actor</h3>
<p>You can find his movies at ${'store'}.</p>
</article>`;
function templater(strings, ...keys) {
return function(data) {
let temp = strings.slice();
keys.forEach((key, i) => {
temp[i] = temp[i] + data[key];
});
return temp.join('');
}
};
const myTemplate = ActorTemplate(Actor);
console.log(myTemplate);
Raw Strings
Our tag functions receive a first argument we called strings, which is an array. But there’s an additional bit of data included: the raw unprocessed versions of all the strings. You can access those raw string values using the .raw property, like this:
function showraw(strings, ...values) {
console.log( strings );
console.log( strings.raw );
}
showraw`Hello\nWorld`;
As you can see, the raw version of the string preserves the escaped \n sequence, while the processed version of the string treats it like an unescaped real new-line. ES6 comes with a built-in function that can be used as a string literal tag: String.raw(..). It simply passes through the raw versions of the strings:
console.log( `Hello\nWorld` );
/* "Hello
World" */
console.log( String.raw`Hello\nWorld` );
// "Hello\nWorld"
It seems for the moment string concatenation is faster: https://jsperf.app/es6-string-literals-vs-string-concatenation
ES6 with variable 19,992,512 ±5.21% 78% slower
String concatenation with variable 89,791,408 ±2.15% fastest
ES6 with function 461,358 ±3.12% 99% slower
String concatenation with function 503,255 ±1.77% 99% slower
I tested was run on Chrome 43.0.2334.0 canary (64-bit), which is using V8 4.3.31, with the #enable-javascript-harmony flag enabled.
For reference, the latest version on Node.js (0.12.0 at the time of writing) is using V8 3.28.73: https://raw.githubusercontent.com/joyent/node/master/ChangeLog
I'm sure all the possible performance optimizations that could be applied have not been applied yet, so it would be reasonable to expect performance to get better as ES6 gets closer to finalization and these features get migrated to the stable branch.
Edit: Thanks for the comments @user1329482, @icl7126, Nicolai Borisik, and FesterCluck. Now that about 2 years have passed since this question was asked, ES6 browser support has greatly increased, and a good amount of performance optimization has taken place. Here are some updates.
Edit: (February 2020) Updated Chrome result based on @JorgeFuentesGonzález comments and subsequent confirmation.
In Chrome (as of 59.0.3035), ES6 string literals are faster:
ES6 with variable 48,161,401 ±1.07% fastest
String concatenation with variable 27,046,298 ±0.48% 44% slower
ES6 with function 820,441 ±1.10% 98% slower
String concatenation with function 807,088 ±1.08% 98% slower
Update: In Chrome (as of 79.0.3945), String concatenation is faster... See comments.
In Firefox (as of 57.0.0), ES6 string literals are faster:
ES6 with variable 1,924,610,984 ±0.50% fastest
String concatenation with variable 1,876,993,458 ±0.79% 3% slower
ES6 with function 539,762 ±5.04% 100% slower
String concatenation with function 546,030 ±5.88% 100% slower
In Safari (as of 11.0.2), it depends:
ES6 with variable 1,382,752,744 ±0.71% fastest
String concatenation with variable 1,355,512,037 ±0.70% 2% slower
ES6 with function 876,516 ±1.01% 100% slower
String concatenation with function 883,370 ±0.79% 100% slower
When using a typecast string, ES6 string literals are faster. However, when calling a function from the literal, string concatenation is faster in this example.
If you really want to go deep and need to squeeze every drop of performance out of Safari, I would suggest setting up tests that see if/how incorrectly typed variables and multiple references within a literal effect performance.
Edit: (July 2024) Updated Chrome result based on historical jsPerf URL from @Paul Lynch.
In Chrome (as of 124.0.0), String concatenation is faster:
ES6 with variable 87,066,798 ±0.60% 89% slower
String concatenation with variable 808,361,236 ±1.11% fastest
ES6 with function 574,631 ±0.21% 100% slower
String concatenation with function 575,763 ±0.22% 100% slower
I did a naive test on node.js v6.0.0 and got nearly the same performance. Since the test is so naive, don't believe the numbers too much. But it seems the JIT compiler generates very optimised code nowadays. This let me decide to prefer templates over concatenation for my node apps.
For reference this is the code I used:
'use strict'
function strConcat(i) {
return 'abc' + i + 'def'
}
function strTemplate(i) {
return `abc${i}def`
}
function run(strategy) {
let before = new Date().getTime()
let len = 0
for ( let i = 0; i < 10000000; i+=1 ) {
len += strategy(i).length
}
console.log(len + ' - ' + ((new Date().getTime()) - before) + 'ms')
}
console.log('strConcat')
run(strConcat)
console.log('strTemplate')
run(strTemplate)
And the output was:
strConcat
128888890 - 1904ms
strTemplate
128888890 - 1979ms
I used len to absolutely make sure that the optimizer doesn't optimize the whole loop away. Anyway, it is still a very simple test. Maybe someone can make a more sophisticated one.
let answer = parseInt(prompt("Please enter a number"));
console.log(`entered number: ${answer}`)
console.log("entered number: %i",answer)
console.log("entered number: " + answer)In Angular js interpolation helps in getting model render on the view. Where as concatenation is to allow the strings to be join together with '+' it may or may not include interpolation .
Example:-
{{}} --> interpolation
It allows your model to bind in view:-
Model:- $scope.name="rachit";
View:- <div>{{name}}</div>
result in View after rendering :- <div>rachit</div>
'+'-->concatenation
It allows to concat the values either in view or in controller or even inside interpolation.
Controller:-
$scope.name="rachit"+"gulati";
View
<div>{{name+name}}</div> //Here interpolation also comes into picture.
result:-"<div>rachitgualtirachitgualti</div>"
UPDATE 1:-
EDIT: Is this interpolation or concatenation (I don't just put strings together but an a variable is resolved here)?
var test1 = "Hello"; var number = 2 + 3; console.log(test1 + " " + number);
It is simple concatenation in javascript here angular is not come into picture.
UPDATE 2:-
Hmm.... I guess whenever I use AngularJS library to combine some expression, then it's interpolation, right?
Concatenation is general term for every programming to concat two strings together.Where as in angualr js interpolation is done by {{}} with the help of $interpolation service.
Interpolation
Interpolation does mean that you want to get the code from the angular scope and show it on html page like suppose we have {{somevariable}} In this eg. it will evaluate the function in angular scope using $interpolation service.
Concatenation
It is used when you want to bind to two strings, It could be do it inside interpolation {{}} directive like {{someVariable + ' test'}} it will concate variable with test result would be someVariable test