Click here to view Part IV: Understanding Destructuring: referencing and defaults.
This article is designed as a “get started” read for beginner to intermediate developers who wish to gain a better understanding of ES6 template literals.
As part of my “Getting to Grips with ES6” series, I aim to create a reference containing straight forward explanations ordered in short sections to help us understand and apply these concepts directly to our current development processes.
Written by Andrew Hill. You can find me on LinkedIn, Twitter, Instagram, and GitHub.
Template literals (also known as template strings in previous versions of the EcmaScript specification), are defined by MDN as string literals that allow for embedded expressions. They provide us with a more concise syntax that gives us more control over how we display string data.
The following example illustrates how one might add a variable to a string before the advent of ES6 and template literals:
var age = 26;
console.log('Andrew is ' + age + ' years old!');
// Output: "Andrew is 26 years old!"
This pattern is applied for any JavaScript expression:
var currentYear = 2016;var birthYear = 1990;
console.log('Andrew is ' + currentYear - birthYear + ' years old!');
// Output: "Andrew is 26 years old!"
The required use of concatenation is unfavorable as it forces us to break up our strings in order to bring in our expressions. Before ES6, JavaScript lacked the ability to simply have an expression interpolated into a string. A feature that has existed for many years in a number of other languages.
In order to construct a template literal, we need to make use of backticks (`
) instead of single or double quotation marks. Expressions are interpolated into the string by encasing them in a dollar sign and curly braces (${}
).
Knowing this, we can rewrite our first example as follows:
const age = 26;
console.log(`Andrew is ${age} years old!`);
// Output: "Andrew is 26 years old!"
We can also rewrite our second example as follows:
const currentYear = 2016;const birthYear = 1990;
console.log(`Andrew is ${currentYear - birthYear} years old!`);
// Output: "Andrew is 26 years old!"
It’s beautiful!
Multiline strings have always been a bit of an eyesore on any JavaScript code base. Each new line would require either escaped characters or concatenation. This is well illustrated by a basic info window being passed to a Google Map:
var title = 'Coffee Shop';var description = 'Drink coffee!';
var infoWindow = '<div>' +'<h3>' + title + '</h3>' +'<p>' + description + '</p>' +'</div>';
console.log(infoWindow);
// Output: "<div><h3>Coffee Shop</h3><p>Drink coffee!</p></div>"
Let’s see what this looks like when written using template literals instead:
const title = 'Coffee Shop';const description = 'Drink coffee!';
const infoWindow = `<div><h3>${title}</h3><p>${description}</p></div>`;
console.log(infoWindow);
// Output: "<div><h3>Coffee Shop</h3><p>Drink coffee!</p></div>"
The template literal version of the info window code is noticeably shorter and far more legible. Our output even maintains line breaks without the use of newline characters.
A less well known feature of template literals is their ability to be interpolated within another template literal. While it might not be something you run into often, it certainly is helpful to know.
We illustrate this point by using a ternary operator to adjust the result of our template literal as follows:
const hungry = true;const foodType = 'pizza';
const foodState =`Andrew is ${hungry ? `hungry for ${foodType}!` : `full!`}`;
console.log(foodState);
// Output: "Andrew is hungry for pizza!"
Template literals have an advanced form known as Tagged Template Literals. Essentially, tagged template literals give us more control by allowing us to modify the output of a template with a named function.
Consider the following example:
const name = 'Damon';
function altered(string, ...values) {return 'Wait, what?';}
const text = altered`The dogs name is ${name}.`;
console.log(text);
// Output: "Wait, what?"
In the example above, the function altered
is overriding the contents of the text
template literal since the function returns the string Wait, what?
. The named function altered
directly controls what is output by the template string.
To create a tagged template literal we first define a named function which returns some value. This value does not need to be a string. The function is called by placing its name before the backticks of the template literal.
Functions used in tagged template literals can receive two arguments, strings
and ...values
. The first argument contains an array of string literals. The final item in the string literals array is always a blank string. In the case of our example, our strings
argument contains the following values:
console.log(strings[0]) // Output: "The dogs name is"console.log(strings[1]]) // Output: ""
The second argument contains the values stored in any variables passed into the string. In the case of our example, the ...values
argument contains the following values:
console.log(values[0]) // Output: "Damon"
These arguments allow for some powerful use cases. Below is an example where we loop over each item in the strings array, and apply <strong>
tags to any variables passed into the string:
function strong(strings, ...values) {let finalString = '';
strings.forEach((string, i) => {if (string !== '') {finalString += `${string}<strong>${values[i]}</strong>`;}})
return finalString;}
var name = 'Damon';var text = strong`The dogs name is ${name}`;
console.log(text);
// Output: "The dogs name is <strong>Damon</strong>"
Thanks for reading. If you liked this article please consider supporting future installations of this series by recommending it. 👏
Click here to view Part IV: Understanding Destructuring: Referencing and Defaults.