Introduction
In this article, we are going to talk about JavaScript Template Literals. They were also called Template Strings prior to the ES2015 specification.
Other than that, we are also going to cover what Tagged Template Literals are and how we can use them with regular Template Literals.
What is a Template Literal?
Template Literals were introduced with JavaScript ES2015 (ES6) to handle strings in an easier and more readable way.
It allows us to embed expressions (expression interpolation) inside a string declaration, handle multi-line strings and create "tagged template literals" which is a more advanced form of template literals.
The Old Way of Handling String Templates
Before ES6, single quotes or double quotes were used to declare a string. Consider the following example:
let x = 'This is a sample string';
let y = "This is a sample string with a 'quote' in it";
let z = 'This is a sample string with a "double quote" in it';
let a = 'This is another sample with a \'quote\' in it';
let b = "This is yet another sample with a \"double quote\" in it";
// a -> This is another sample with a 'quote' in it
// b -> This is yet another sample with a "double quote" in it
Generally, we used the single quote declaration by default, and the double quote declaration if the string contains single quotes within it. The same applied the other way around - we use whatever quotes allow us to avoid using escape characters like in a
and b
.
Also, if we wanted to concatenate two strings, the plus operator was the most common way to do that:
let firstName = 'Janith';
let lastName = 'Kasun';
let fullName = firstName + ' ' + lastName;
// fullName -> Janith Kasun
If we wanted to include white spacing (including the tab and new line), we used the new line character (\n
) and the tab space character (\t
) to do that.
The old syntax did not allow breaking the text into the next line without using special characters such as the newline:
let info = 'Name:\tJohn Doe\n'
info = info + 'Age:\t20\n';
info = info + 'City:\tLondon';
console.log(info);
Running this code would result in:
Name: John Doe
Age: 20
City: London
However, as you can see in this example, using special characters reduces the code's readability.
ES6 Template Literals
The interchangeable use of single quotes ('
) and double quotes ("
), as well as the use of special and escape characters can make things a bit tricky in certain situations. Let's see how we can avoid these issues by using template literals.
Declaring a Template Literal
JavaScript template literals use the backtick character (`) to declare a string instead of single or double-quotes. For example:
let x = `This is a new template literal`;
You can use the quotes and double quotes inside the string declaration with template literals:
let y = `This is a string with a 'single quote'`;
let z = `This is a string with a "double quote"`;
Multi-line String and Tabs
With template literals, we can just add a new line inside the declaration itself. Instead of using the new line character, we can simply break the code into the next line:
console.log(`This is the first line
This is the second line`);
This code results in:
This is the first line
This is the second line
Expressions with Template Literals (Expression Interpolation)
If the only feature of Template Literals was avoiding the misuse of single and double quotes and breaking lines, they wouldn't be a game-changer. However, building dynamic strings and text was made really easy with the inclusion of expressions.
You can add an expression within a template literal and the resulting string will contain the evaluated value of the expression. For example, without template literals, we could be looking at something along the lines of:
let a = 5;
let b = 10;
console.log('The sum of ' + a + ' and' + b + ' is ' + (a + b));
This would result in:
The sum of 5 and 10 is 15
Now, that's fine on the resulting end. But having to break the string in several places and adding the values like this is unreadable when you have more than just simple addition. Not to mention, a single typo can cause issues with implicit data type conversions and the whole statement becomes incorrect.
With template literals, we can simply add expressions, following the ${...}
syntax, directly into string declarations. When we run the code, the expressions are evaluated and their values are put in:
let a = 5;
let b = 10;
console.log(`The sum of ${a} and ${b} is ${a+b}`);
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
This also results in:
The sum of 5 and 10 is 15
This is a much cleaner solution to a fairly rudimentary task. Let's rewrite the whitespace example from before, using template literals:
let info = `Name: John Doe
Age: 20
City: London`;
console.log(info);
However, static information like this is rarely used. Let's populate an object with the same information and then read its values:
const person = {
firstName: 'John',
lastName: 'Doe',
age: 20,
city: 'London'
}
let info = `Name: ${person.firstName} ${person.lastName}
Age: ${person.age}
City: ${person.city}`;
console.log(info);
This also results in:
Name: John Doe
Age: 20
City: London
Tagged Template Literals
Tagged Template Literals provide a more advanced usage of template literals using a customizable function.
Consider the following scenario.
There is a result sheet from a recent exam. The pass mark for the exam is 50. We want to create a tagged template that outputs if the candidate has passed the exam or not.
For example, the app would display "John has passed the exam" or "Ann has failed the exam", based on their mark.
Let's define a tagged template function that determines if the student has passed or failed:
function exampleTag(personExp, strings, marksExp) {
let resultStr;
if (marksExp >= 50) {
resultStr = 'passed';
} else {
resultStr = 'failed'
}
return `${personExp}${strings[0]}${resultStr}`;
}
Here, based on the parameters passed to the exampleTag()
function, we determine if the result is set to be passed
or failed
. Ultimately, we return a template literal. This template literal contains expressions that represent the person's name, a string and the marks.
Let's make a couple of people and pass them to the function:
let p1 = {
person: 'John',
marks: 45
}
let p2 = {
person: 'Ann',
marks: 67
}
let ex1 = exampleTag`${p1.person} had ${p.marks}`;
let ex2 = exampleTag`${p2.person} had ${p.marks}`;
console.log(ex1);
console.log(ex2);
Running this code will result in:
John had failed
Ann had passed
Although we just have one string here, had
, we could've easily had many. Thus, the strings
parameter is an array. You can reference each passed string, in accordance to their appearance in the template literal passed to the exampleTag()
function.
Raw Strings
Finally, let's talk about the raw
property when creating a tagged template literal.
This property is available on the first parameter of the tagged template. It allows you to get the value of the raw string without processing the escape characters from it.
Consider the following example:
function rawTag(strings) {
console.log(strings.raw[0]);
}
rawTag`this is a \t sample text with \ escape characters \n\t`;
This would result in:
this is a \t sample text with \ escape characters \n\t
As you can see, we can use escape characters as raw text using the raw
property with tagged templates.
You can also use the String.raw()
function to do that, which is a built-in JavaScript tagged template literal that allows you to declare raw strings without processing the escape characters.
You can simply use this if you don't need any additional logics:
let rawString = String.raw`this is a \t sample text with \ escape characters \n\t`
This also results in:
this is a \t sample text with \ escape characters \n\t
Conclusion
In this article, we've covered the old way of handling dynamic strings, whitespaces and escape characters. Then, we've jumped into template literals, expressions within template literals and finally tagged template literals.