Template literals or string literals is a new JavaScript feature that enhances the ways in which developers can work with strings. It adds functionality for expression interpolation, multi-line strings, nesting templates, and tagged templates. These features make your code more usable and readable. Let’s learn how to use template literals in our JavaScript applications.
A Problem Old as Time
If you’ve done any sort of programming, you’ve almost certainly worked with strings. If you haven’t, I would really love to talk to you. Strings are powerful primitives in many programming languages, including JavaScript. Because strings are such a flexible primitive, they allow you to shoot yourself in the foot quite easily.
JavaScript has traditionally allowed developers to use both single-quotes ('
)
and double-quotes ("
) to represent string values. Template literals introduce
a third way which uses backticks (`). We’ll go into what that means in just a
minute, but first let’s take a look at some classic problems developers will
likely encounter when working with strings in JavaScript.
// Mismatched case
console.log("My amazing message');
// Uncaught SyntaxError: Invalid or unexpected token
// Does not close the string with double-quotes
console.log('My amazing message");
// Uncaught SyntaxError: Invalid or unexpected token
// Does not close the string with single quotes
// String concatenation
console.log("Back in my day" + "working with strings was a lot harder.");
// "Back in my dayworking with strings was a lot harder."
// Need to add a space before the w, i.e " working..."
// Multi-line
console.log("I've always wanted to \n write good code");
/*
"I've always wanted to
write good code"
*/
// Remembering special characters and escape notations
console.log('I've always wanted to write good code');
// Uncaught SyntaxError: missing ) after argument list
// Missing escape character \
I could go on but you get the point. While none of these problems are necessarily hard to fix, they do present a great annoyance to developers. Enter template literals which solve almost all of the nuances of working with strings and more.
Better Strings with Template Literals
To use the new and improved way of working with strings in JavaScript all you have to do is wrap your strings in backticks (`) instead of single or double quotes. Let’s see some examples.
var name = `Ado Kukic`
console.log(`This doesn't seem all that different`)
All modern browsers support the template literals syntax but if you need legacy browser support there are polyfills as well as transpilers like Babel or Webpack that can help. On the surface, using this new syntax doesn’t seem like it changes the string story too much. Instead of single or double quotes, you’re now just adding a third way of wrapping strings. How is this any better? Just you wait.
Expressions
The biggest feature that template literals add in my opinion is expression interpolation. If you have worked with frameworks like Angular or React, you’ve been using interpolation for your templates and I bet you can’t go back. Let’s see how this works. With the traditional JavaScript string syntax if we wanted to do embed expressions into our strings we would have to do something like this:
var firstName = 'Ado'
console.log('Your first name is: ' + firstName + ', correct?')
Alternatively, you might have seen string substitution used to make your code a bit more readable like this:
var firstName = 'Ado'
var lastName = 'Kukic'
var age = 29
console.log('Your first name is: %s, correct?', firstName)
// "Your first name is: Ado, correct?"
console.log('Your full name is %s %s', firstName, lastName)
// "Your full name is Ado Kukic"
console.log('%s %s, %d', firstName, lastName, age)
// "Ado Kukic, 29"
There are a number of different string substitution options. We saw %s
for
strings, %d
for numbers, but there are others like %j
for JSON and %o
for
object. String substitution helped clean up our code a little bit, but it was
not ideal. You had to pass in the variables in the right order, you had to
remember the different string substitution patterns, and most importantly this
only works in logging to the console.
Template literal expressions gave us a clean way of interoperating the rest of our code with our strings. Let’s see some examples.
// Using double quote string syntax
var firstName = 'Ado'
// Using string literal syntax
var lastName = `Kukic`
// Using string literal syntax
var fullName = `${firstName} ${lastName}`
console.log(fullName)
// "Ado Kukic"
The syntax for expression interpolation is ${}
. Anything we place between the
curly brackets will be executed as code. In here we can pass variables,
functions, or other logic that will be evaluated and it’s final value displayed.
Let’s look as some more concrete examples.
var job = 'Developer Evangelist'
function fullName() {
var firstName = 'Ado'
var lastName = 'Kukic'
return `${firstName} ${lastName}`
}
console.log(`Hi my name is ${fullName()} and I work as a ${job}`)
// "Hi my name is Ado Kukic and I work as a Developer Evangelist"
Express interpolation makes our code much cleaner and easier to read. Finally, we can use expression interpolation in both debugging and throughout our codebase wherever we work with strings.
Multi-line Strings
Multi-line strings in JavaScript without template literals were a pain. If you wanted your string content to be displayed in multiple lines you had to do this:
console.log(
'Haikus are easy\n' + "But sometimes they don't make sense\n" + 'Refrigerator'
)
// Or
console.log(
"Haikus are easy\nBut sometimes they don't make sense\n Refrigerator"
)
The use of the \n
escape character to start a new line interwoven with the
rest of your string made your code really hard to read. If you opted for
readability, you had to use the +
to concatenate your strings, otherwise if
you did everything in one line your code was very difficult to read.
Luckily, the template literal syntax allows us to add multi-line strings with minimal effort. Let’s look at an example.
let haiku = `Haikus are easy
But sometimes they don't make sense
Refrigerator`
console.log(haiku)
/*
Haikus are easy
But sometimes they don't make sense
Refrigerator
*/
As you can see, we didn’t need to do anything special here. We declared our
string using the template literal syntax and broke up our string into multiple
lines within our editor, and when we printed out the string it was printed out
in the format we had created in. No need for special characters, but if for
whatever reason you wanted to use \n
or \t
you could and they would behave
as expected.
Nesting Templates
You can also nest your template literals inside of each other. A potential use case for this may be wanting to have a more readable way of managing white label configurations in your application for example. The syntax for this is fairly simple, all you do is simply nest your literals within each other - inception style. Let’s see how this works.
let name = `Ado ${`Kukic`}`
console.log(name)
// "Ado Kukic"
If you’re working with known values already then the above example is overkill. Let’s see a bit more of a concrete example.
let message = `You are a ${`super-${isHero() ? 'hero' : 'villain'`}`}`;
// "You are a super-hero" if isHero() returns true
// "You are a super-villain" if isHero() returns false
While nesting templates are powerful, if you end up using them often I would evaluate your code to see if there are improvements that can be made to not rely on them as much. The nesting code is pretty hard to read and my recommendation would be to avoid nesting templates if possible.
Tagged Templates
Finally, we get to the more advanced uses of template literals with tagged templates. Tagged templates allow you to parse a template literal with a custom function. The tagged template function is written much like any other JavaScript function, with the only requirement being that the first parameter or argument passed in is a strings array. Let’s see an example.
function taggedTemplate(strings, otherArgument) {
// Implementation details
}
You can have as many additional parameters passed into the taggedTemplate
as
you desire to get the job done and they can be of any type. To use
taggedTemplate
in our JavaScript code, the syntax is a bit different from a
traditional function. Let’s see an example.
var message = taggedTemplate`What the heck is this?`
Yeah the syntax is a little bit wonky. You call your tagged template function
and instead of using parenthesis you just append your string in the template
literal format. Since we haven’t added any implementation details to our
taggedTemplate
function, let’s go back and make some changes to see how this
whole tagged template thing works.
function taggedTemplate(strings, otherArgument) {
return `I wonder what this will do`
}
var message = taggedTemplate`What the heck is this?`
console.log(message)
// "I wonder what this will do"
As you can see whatever value we return from our taggedTemplate
function will
be what is logged to our console. In the above example, we sent back a
completely different message. While this is possible, I can’t really think of a
good use case where you would use it. So let’s what else we can do.
function taggedTemplate(strings, otherArgument) {
var firstWord = strings[0]
var secondWord = strings[1]
return `${firstWord} came before ${secondWord}`
}
var message = taggedTemplate`What the heck is this?`
console.log(message)
// "What came before the"
Ok, I can see how this might be a bit more useful. But what about that second
parameter we’re passing in, the otherArgument
. Well at the moment, we’re not
passing anything additional into our taggedTemplate
function. The way we pass
the additional arguments is by passing in template literals in our initial
message.
function taggedTemplate(strings, amount) {
if (amount > 100) {
var message = `Doing great!`
} else {
var message = `Keep at it!`
}
return `Great start! ${message}`
}
var amount = 500
var message = taggedTemplate`I have ${amount} dollars!`
console.log(message)
// "Great start! Doing great!"
As you can see when we add expressions to our template literals, they get
translated as arguments in our tagged templates. The order here matters so the
first expression will be mapped to the first argument after the strings
argument, the second to the second, and so on. Tagged templates give us a lot of
power and flexibility when it comes to manipulating our strings and formatting
them just the way we want. Tagged templates can be a great help when you need to
manipulate the DOM from JavaScript in your applications.
Performance Considerations
Template literals are great, make our code a lot more readable, and give us a couple of new features to play with, so there must be a catch somewhere right? Luckily, there is no catch. Using the template literal syntax is just as performant as using the traditional way of working with strings in JavaScript. Since template literals are still a fairly new way of working with strings in JavaScript, performance will likely only improve in the future.
Conclusion
Template literals supercharge the way developers work with strings in JavaScript. The addition of expression interpolation, easy multi-line strings, nested and tagged templates address common issues developers encounter when working with strings and also add new ways of manipulating and working with them. Since all modern browsers support template literals, don’t wait another day to incorporate them into your JavaScript applications.