DEV Community

Paige Niedringhaus
Paige Niedringhaus

Posted on • Originally published at paigeniedringhaus.com on

String Template Literals: JavaScript ES6 Feature Series (Pt 5)

Close up of ink pen writing on paper

Introduction

The inspiration behind these pieces is simple: there are still plenty of developers for whom JavaScript is somewhat mysterious. I agree, there’s a lot to understand — it’s a complex language, once you’ve scratched the surface.

However, JavaScript powers 95% of the most popular web pages online today, according to Wikipedia, and on top of that the ECMAScript committee keeps releasing updates on a yearly basis. It’s a lot to keep up with.

Since these changes are coming so fast and furious, I wanted to provide articles and examples of ES6+ features that I use regularly, for other developers to reference.

The aim is to keep these articles short. I will provide in-depth explanations of various improvements to the language, that I hope will inspire you to write some really cool stuff using JavaScript. Who knows, you might even learn something new along the way!

In my fifth piece, I’ll be discussing template literals: the newest, easiest way to work with strings in JavaScript.


Template Literals

Strings are one of the main JavaScript objects types. All they are is sequences of characters wrapped between single-quotes '' or double-quotes "".

Anatomy of a traditional string

const string1 = 'this is a string in single quotes';

const string2 = "this is a string in double quotes";
Enter fullscreen mode Exit fullscreen mode

The string type values above are immutable (unchangeable), but string objects, created by using the String() constructor, are mutable, because they are objects and you can add new properties to them.

But that’s JavaScript 101 and besides the point of this article. What I’m excited to talk about is template literals (known as "template strings" pre-ES2015).

To get us started, here’s the official MDN definition of template literals:

"Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them." — MDN web docs

What do I mean when I say "embedded expressions" or "string interpolation features"? I’m so glad you asked, let me show you!

Template literals syntax

// just a normal string in one line - not much different from a traditional string
const simpleString = `a template literal is surrounded by backticks`;

// a string spread across multiple lines
const multiLineString = `it can be spread across
multiple lines with just 
one set of enclosing backticks`;

const name = "Paige";

// an expression placeholder allowing a variable to be injected into the string
const greetByName = `Hello, ${name}`;

console.log(greetByName); // 'Hello, Paige'
Enter fullscreen mode Exit fullscreen mode

These three examples show what you can do with template literals.

The first, simpleString, is a single line string much like a normal JavaScript string surrounded by traditional quotes.

The second, multiLineString, is a multi-line string (return characters included even though you don’t see the \r characters for them), that will print out exactly the way it’s written above.

The third is an example of an expression placeholder, where the variable name is inserted into the string greetByName.

Now that I’ve shown you the quick way to use template literals, let’s get into the details of what you need to know about them.

Defining traits of template literals

Template literals have a number of characteristics that make them different from JavaScript strings of yesteryear. These same subtle differences also make them a lot more useful, in my opinion.

Here’s what makes template literals unique.

Backticks

The easiest way to identify template literals is by the backticks (``) (also known as the grave accent) surrounding the characters instead of single or double quotes.

For Mac users, the backtick key is located in the top left of the keyboard. It’s the same key you use for tildes ~ in the command line terminal.

Backtick string examples:

`javascript
/* your basic JavaScript strings, but with backticks.
notice the lack of escape characters needed for things
like single quotes, double quotes, and apostrophes
when backticks are employed */

const fooString = A string called 'fooString';

const barString = Another string named "barString";

const bazString = Without fooString and barString, you can't have bazString, right?;
`

NOTE: If you need to write a backtick inside a template string, you must escape it with a backslash. \ is the same as "`".

Some JavaScript developers have even suggested using Prettier and other auto-formatters to change all their strings to use backticks all the time. I myself default to using single quotes, unless I need the power of template literals, but that’s just me!

Expression placeholders

Template literals can contain placeholders, which are indicated within the string by the dollar sign and curly braces (${variableExpression}). The expressions in the placeholders and the text between the backticks () get passed to a function.

Expression placeholder examples:

`javascript
function authorize(user, action) {
if (!user.hasPermission(action)) {
throw new Error(
User ${user.name} is not allowed to ${action}.
);
}
}

const person = {
name: "Sean"
};
const activity = "bake";

console.log(authorize(person, activity));
// "User Sean is not allowed to bake."
`

Multi-line strings

Any newline characters inserted in the source are part of the template literal. Instead of having to use the \n and + sign to concatenate two strings together to have a multi-line string, the whole string can be done as one.

Original way to create a multi-line string example:

`javascript
console.log("To make a multi-line string this way\n" +
"I have to concatenate two separate strings with a + sign");

/* prints: To make a multi-line string this way
I have to concatenate two separate strings with a + sign */
`

Template literal way to create a multi-line string example:

`javascript
console.log(With template literal backticks, I can spread strings across
as many lines as I want
with
no
problem.
);

/* prints: With template literal backticks, I can spread strings across
as many lines as I want
with
no
problem. */
`

Expression interpolation

Embedding expressions (like simple math calculations) into strings used to be quite cumbersome to write out (and interpret) in code.

String concatenation to insert expression values into them:

`javascript
const c = 10;
const d = 5;

console.log('It used to be harder to calculate that ' + (c + d)

  • '\n is not the same as ' + (2 * c) + ' in a string.');

/* prints: It used to be harder to calculate that 15
is not the same as 20 in a string. */
`

Template literals make use of syntactic sugar to make substitutions like this much more readable.

Expression interpolation inside of string template literals:

`javascript
const c = 10;
const d = 5;

console.log(With the syntactic sugar of ES6 template literals,
doing math in strings like this: ${c + d}
and that: ${2 * c} is a cinch.
);

/* prints: With the syntactic sugar of ES6 template literals,
doing math in strings like this: 15
and that: 20 is a cinch. */
`

Nesting templates

Sometimes nesting a template is the easiest and most readable way to have configurable strings. It’s simple to allow inner backticks within a backticked template by using them inside a placeholder, ${ }, within the template. This could be useful in cases where you’re using a ternary to determine which template literal return.

Configuring strings prior to nested templates:

`javascript
var classes = 'header';

function isDesktopSize(){
window.innerWidth > 1400 ? true : false;
};

var navbar = {
isOpen: false
};

classes += (isDesktopSize() ?
'' : navbar.isOpen ?
' collapse-navbar' : ' expand-navbar');

console.log(classes);

// prints: header expand-navbar
`

Nested templates to create configured strings:

`javascript
function isDesktopSize(){
window.innerWidth > 1400 ? true : false;
}

var navbar = {
isOpen: true
};

classes = header ${ isDesktopSize() ? '' :
icon-${navbar.isOpen ? 'collapse' : 'expand'} };

console.log(classes);

// prints: header icon-collapse
`

Nested ternaries (which are used in both configurable string examples) are a generally frowned-upon coding practice, but I used them anyway in the examples to illustrate how the classes variable can be configured so much more cleanly.

NOTE: in actual coding, it’s suggested to use if / else / if statements if you find yourself dealing with nested ternaries.

Tagged templates

More advanced forms of template literals are tagged templates.

Tags allow you to parse template literals with a function. The first argument in a tag function contains an array of string values. The remaining arguments are related to the expressions. In the end, the function can return a manipulated string (or it can return something completely different). The name of the function used for the tag can be whatever you want.

Tagged template example:

`javascript
var guy = 'Paul';
var age = 96;

function myTag(strings, personExp, ageExp) {
var str0 = strings[0]; // "That "
var str1 = strings[1]; // " is a "

var ageStr;
if (ageExp > 99){
ageStr = 'centenarian';
} else {
ageStr = 'youngster';
}

// You can even return a string built using a template literal - just to be fancy
return ${str0}${personExp}${str1}${ageStr};
}

var output = myTagThat ${ guy } is a ${ age };

console.log(output);
// prints: That Paul is a youngster

var lady = 'Elizabeth';
var age = 107;

var output = myTagThat ${ lady } is a ${ age };

console.log(output);
// prints: That Elizabeth is a centenarian
`

Pretty neat!

Raw strings

The special raw property, available on the first argument of the tag function below, lets you access raw strings as they were entered, without processing escape sequences (\t, \v, \n, \r, etc.).

Raw property on a template literal string example:

`javascript
function tag(strings) {
console.log(strings.raw[0]);
}

tagI'd like this line 1 \n to ignore the newline and be in line with 1
\n even though I should be on line 3 at this point
;

/* prints: I'd like this line 1 \n to ignore the newline and be in line with 1
\n even though I should be on line 3 at this point */

// including the two characters '\' and 'n' multiple times
`

Additionally, the String.raw() method exists to create raw strings just like the default template function and string concatenation would.

Raw property with expression interpolation and string methods example:

`javascript
var str = String.rawWhat's up \n${4+7}?;
console.log(str);
// prints: What's up \n11?

console.log(str.length);
// prints: 15

console.log(str.split('').join(','));
// prints: W,h,a,t,',s, ,u,p, ,\,n,1,1,?
`

I’m not sure how often you’ll need this in the real world, but it’s nice to know it’s there.


Conclusion

Every year ECMAScript releases new updates to the JavaScript language designed to make developers’ lives easier. At first glance, the syntax can seem quite alien — even to veteran JavaScript developers. However, it’s well worth your time to learn the new tricks — they’ll bring so much power to your development.

My aim with this blog series is to explain some of my favorite parts of the JavaScript and ES6 syntax being used everywhere now, and show you how to use the newest parts to maximum effect.

Strings are one of the most basic parts of the JavaScript language, but when ES2015 came around it introduced template literals and these once humble objects got a lot of upgrades. Injecting variables, performing expressions, even making multi-line strings — once complicated code is a breeze thanks to template literals.

Check back in a few weeks, I’ll be writing about more JavaScript and ES6 or something else related to web development.

If you’d like to make sure you never miss an article I write, sign up for my newsletter here: https://paigeniedringhaus.substack.com

Thanks for reading, I hope you’ll give template literals in their many forms a try — they make strings in JavaScript so much easier to work with.


References & Further Resources

Top comments (0)