ES6 Tutorial: Template Literals And Tagged Templates6 min read
In this tutorial, we are going to learn a concept that is pretty easy in JavaScript but very useful, which is the template string.
Before JavaScript ES6, we either indicate a string using single-quotes or double-quotes. It simples like this:
var a = "This is a string";
var b = 'This is another string';
However, there are some inconveniences when working with this. If you want single quotes or double quotes displayed inside your string, you have to use double quotes and single quotes respectively to wrap your string:
var c = "Hello I have some single quotes here: ''''";
console.log(c); // Hello I have some single quotes here: ''''
var d = 'Hi, I have some double quotes here: """';
console.log(d); // Hi, I have some double quotes here: """
When you to put a variable inside a string, the only thing you can do is forcing yourself to stop a string, then concatenate to the variable, then open your string again if you want:
var foo = 5;
var w = 0.5
var bar = "Hi, I don't know about you but for me " + foo + " and " + w + " years is a quite long time.";
console.log(bar);
// Hi, I don't know about you but for me 5 and 0.5 years is a quite long time.
Each time you need to stop your string, quite miserable. We can get rid of all unease stuff above by using template strings.
Template Strings Syntax
Template strings are string literals but they allow you to embedded expressions. It also can be called String Interpolation.
`single line string`
`string with multiple lines
the second line
the third line
...
`
`cool string with ${expression} another string`
With template strings, we can easily write a string with a pair of backticks. Inside those backticks, is the thing you want to display with your string, it can be anything. Instead of writing "\n"
for each time you want to get to the new line, you can just press enter. Also, template literals can contain placeholders, which means you can put variables inside your string with this ${yourVariable}
syntax:
var x = `a string on a single line`;
var y = `strings in multiple lines
something here...
`
var tenX = 10;
var z = `What is ${tenX}x engineer? `;
console.log(x);
console.log(y);
console.log(z);
/*
a string on a single line
strings in multiple lines
something here...
What is 10x engineer?
*/
The code fragment has shown us the features of template strings, you can write a string in one line, or multiple lines, or embed expressions by passing a variable with backticks.
Inside the ${}
is the expression, which means you can likewise perform some calculation inside it and get the result:
var a = 5;
var b = 10;
var c = `Five plus ten equals ${a + b}`;
console.log(c);
// Five plus ten equals 15
The ${}
syntax only works inside the backticks, if you wrap it with single quotes or double quotes, it doesn’t work:
var five = 5;
console.log("${five}"); // ${five}
console.log('${five}'); // ${five}
Tagged Template Literals
Tagged template literal is the advanced concept of template strings, it allows you to pass a string through a function. The first argument of the tag function contains an array of string values from your template literals, the rest arguments contain the expressions of your template literal.
So what, why should I know this thing? Well, the tag function can make your string become dynamic, it can then perform whatever operations on these arguments you wish, and return the manipulated string. It’s hard and obscure to envision without examples, this concept made me quite confused for a while. Now let’s make some examples to clarify this thing.
Firstly, we need to define some variables act as expressions inside the template literal:
var a = 5;
var b = 7;
var c = 10;
var d = `Hello world ${a}, ${b}, ${c}`;
Now let’s define a tag function and add it to the front of our variable d
:
var a = 5;
var b = 7;
var c = 10;
function taggedTemplate(strings, ...values) {
console.log(strings);
console.log(values);
}
var d = taggedTemplate `Hello world ${a} ${b} ${c}`;
Let’s run this code real quick to see what we get:
[ 'Hello world ', ' ', ' ', '' ]
[ 5, 7, 10 ]
Basically, the content inside the template literal will be passed in the taggedTemplate
function. The first argument is the string values, which is an array contains all of the string inside the template literal. The rest argument contains the values of expressions inside the template string.
so what exactly are string values we pass into the first argument of the taggedTemplate
function?
Start from the beginning of the template, the taggedTemplate
function searches for the string values, whenever it finds the expression, it stops and adds this string to the strings
array, which is our first argument:
`Hello world ${a} ${b} ${c}`;
↑ found an expression ${a} here, stops and add string "Hello world " to the array:
["Hello world "]
Then it continues this process with the rest of the string to find the string values to add to the first argument of taggedTemplate
function:
` ${b} ${c}`;
↑ found an expression ${b} here, stops add add string " " (just a space string) to the array:
["Hello world ", " "]
Do it again:
` ${c}`
↑ found an expression ${c} here, stop and add the string before this
expression to the string array, it also adds the empty string after the
expression ${c} to the string array:
["Hello world ", " ", " ", ""]
Next, we examine the values of the rest arguments in the taggedTemplate
function, those values are the expressions inside the template literal, the result is stored in an array:
${a}, ${b}, ${c}
[5, 7, 10]
So again we have those values are passed into the taggedTemplate
function:
strings = ["Hello world ", " ", " ", ""]
values = [5, 7, 10]
However, why the second parameter is ...values
and not values
? Because we want to take an arbitrary number of the elements when we pass to the second argument, the ...
3 dots syntax is the rest operator, which we will learn more later. Basically it takes all the rest of the arguments we pass to the function and dense it to an array as we have in the values argument. But why don’t just use taggedTemplate(strings, a, b, c)
? We don’t know how many numbers of expressions we have in the template literal, so when we have 4 expressions we have to change the parameters of the function again (taggedTemplate(strings, a, b, c, d)
), the same thing happens with 5, 6, 100…expressions. With rest operator, problem solved when we store all the rest arguments to the one unite array.
Let’s solidify this by do one more example:
var name = "Nam"
var age = 17;
function taggedTemplate(strings, ...values) {
console.log(strings); // ["This person ", " is ", " years old."]
console.log(values); // ["Nam", 17]
var string = strings[0]; // "This person "
var getAge = values[0]; // 17
var isAdult;
if (getAge >= 18) {
isAdult = "an adult"
} else {
isAdult = "not an adult";
}
return `${string} ${name} is ${isAdult}`
}
var d = taggedTemplate `This person ${name} is ${age} years old.`;
console.log(d); // This person Nam is not an adult
This example is quite the same as the thing we did above, we just added an extra step by logging out the value of d
variable, and inside the taggedTemplate
function we have 2 variables and we assign the values of the template literal to those variables, then underneath them, we check whether the age is equal or greater than 18 or not then store this value to the variable isAdult
. Finally, we return the value with some variables we defined within this function. Note that we also can return a template literal.