In this article, you will learn about the differences between regular string values, specified with single or double quotes, and template literals. You will learn about different ways of declaring strings with different characteristics, including multiline strings and dynamic strings that change depending on the value of a variable or expression. You will learn how to work with tag templates and see real-world examples of their use.
Declaring strings
In this section, we recall how strings are declared using single or double quotes, and then take a look at how the same is done when using template literals.
A JavaScript string can be thought of as a sequence of characters enclosed in single quotes (
' '
):
const single = 'Every day is a good day when you paint.'
Another way to declare strings is to use double quotes (
" "
):
const double = "Be so very light. Be a gentle whisper."
In JavaScript, there are no major differences between such strings. In other languages, using different quotation marks when declaring strings can mean, for example, that strings of one kind can be interpolated while others cannot. Here we mean by "interpolation" the ability to compute the values of placeholder expressions that play the role of dynamic parts of strings and participate in the formation of the resulting string values.
Which strings to use when declared with single or double quotes is largely a matter of personal preference and coding conventions. However, if the same type of quotation mark occurs in a string delimited by one of these types of quotation marks, they must be escaped . Quotes of a different kind in such strings do not need escaping.
// ,
const single = '"We don\'t make mistakes. We just have happy accidents." - Bob Ross'
// ,
const double = "\"We don't make mistakes. We just have happy accidents.\" - Bob Ross"
console.log(single);
console.log(double);
Calling a pair of methods
log()
will result in two identical lines being sent to the console .
"We don't make mistakes. We just have happy accidents." - Bob Ross
"We don't make mistakes. We just have happy accidents." - Bob Ross
Template literals, on the other hand, are declared using backticks (
` `
):
const template = `Find freedom on this canvas.`
There is no need to escape single or double quotes here:
const template = `"We don't make mistakes. We just have happy accidents." - Bob Ross
But backticks in such strings must be escaped:
const template = `Template literals use the \` character.`
Template literals have all the capabilities of regular strings. Therefore, you can probably replace all strings in your project with template literals without losing anything. Most often, however, coding conventions specify that template literals should only be used when their special capabilities are needed. Ordinary strings are always declared using either single or double quotes to maintain code consistency. The code base of the project, when writing which follows this standard, will be easier to read for developers who are not previously familiar with it.
Now that we've talked about declaring strings using single quotes, double quotes, and backticks, we can move on to the first strength of template literals. Namely - to the possibility of describing multi-line strings.
Multi-line strings
In this section, we'll first talk about how multiline strings were declared before ES6, and then we'll look at how template literals simplify this task.
Initially, if you had to enter a string variable consisting of several lines in a text editor, the string concatenation operator was used . The following string concatenation example illustrates this idea:
const address =
'Homer J. Simpson' +
'742 Evergreen Terrace' +
'Springfield'
This approach can allow you to break long lines into small chunks and arrange them in a text editor on several lines. But this does not in any way affect how the final row will turn out. In this case, the value of the string constant will be located on one line. The parts from which the string value is assembled will not be separated by line feeds or spaces. If you print a constant to the console
address
, the following will appear there:
Homer J. Simpson742 Evergreen TerraceSpringfield
Another approach to writing such lines in code editors is to use the backslash character (
\
), which is placed at the end of line fragments, and after which, on a new line, new fragments are located:
const address =
'Homer J. Simpson\
742 Evergreen Terrace\
Springfield'
With this approach, for example, the spaces before the fragments of the line are preserved, but the value of the variable, if you print it to the console, will again be represented by a single line:
Homer J. Simpson 742 Evergreen Terrace Springfield
You can create a real multiline string using the linefeed character (
\n
):
const address =
'Homer J. Simpson\n' +
'742 Evergreen Terrace\n' +
'Springfield'
When displaying a string value stored in the console
address
, this value will span multiple lines:
Homer J. Simpson
742 Evergreen Terrace
Springfield
However, using the newline character to create multi-line strings is not particularly convenient and easy. On the other hand, creating multi-line strings using template literals is much easier and more convenient. No need to concatenate strings, no need to use newline or backslash. To create multi-line strings using template literals, it is quite simple, at the end of the next fragment of a line, press the key
Enter
, and continue entering the next line of the template literal:
const address = `Homer J. Simpson
742 Evergreen Terrace
Springfield`
If you output this constant to the console, the text will look the same as in the editor:
Homer J. Simpson
742 Evergreen Terrace
Springfield
Here it should be borne in mind that if there are spaces between backticks used to align the code, these spaces will be included in the final template literal. Consider the following example:
const address = `Homer J. Simpson
742 Evergreen Terrace
Springfield`
Although this style of coding makes it easier to read, what gets to the console after outputting it won't look very attractive:
Homer J. Simpson
742 Evergreen Terrace
Springfield
Now, having dealt with multi-line strings, let's talk about how you can embed the results of evaluating various expressions into strings declared in different ways, that is, let's talk about interpolating expressions.
Expression Interpolation
Previously, before ES6, concatenation was used to create dynamic strings that involved variable or expression values:
const method = 'concatenation'
const dynamicString = 'This string is using ' + method + '.'
If you output
dynamicString
to the console, you get the following:
This string is using concatenation.
When using template literals, expressions can be embedded in the string using placeholders. A placeholder is a view construct
${}
. In this case, everything contained in curly braces is considered as JavaScript code, and everything outside this construction is considered as a string:
const method = 'interpolation'
const dynamicString = `This string is using ${method}.`
When outputting
dynamicString
to the console, you get the following result:
This string is using interpolation.
A common example of embedding values in strings is creating dynamic URLs. The use of concatenation for this purpose leads to the appearance of cumbersome and inconvenient structures. For example, here's a function that generates an OAuth access string :
function createOAuthString(host, clientId, scope) {
return host + '/login/oauth/authorize?client_id=' + clientId + '&scope=' + scope
}
createOAuthString('https://github.com', 'abc123', 'repo,user')
If you print the result of this function to the console, you get the following:
https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user
When using interpolation, programmers no longer need to be careful about the quotation marks that delimit portions of the string, and where exactly the concatenation operator is located. Here is the same example, rewritten using template literals:
function createOAuthString(host, clientId, scope) {
return `${host}/login/oauth/authorize?client_id=${clientId}&scope=${scope}`
}
createOAuthString('https://github.com', 'abc123', 'repo,user')
The result of the function will be as follows:
https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user
You can use the trim () method to remove leading and trailing whitespace from a string created with a template literal . For example, in the following code snippet to create an HTML elementwith a custom reference, an arrow function is used :
const menuItem = (url, link) =>
`
<li>
<a href="${url}">${link}</a>
</li>
`.trim()
menuItem('https://google.com', 'Google')
Leading and trailing spaces will be removed from the final line to ensure that the element is rendered correctly:
<li>
<a href="https://google.com">Google</a>
</li>
Whole expressions can be interpolated, not just variables. For example - like here, where the result of adding two numbers is embedded in a string:
const sum = (x, y) => x + y
const x = 5
const y = 100
const string = `The sum of ${x} and ${y} is ${sum(x, y)}.`
console.log(string)
Here function
sum()
and constants are declared x
and y
. After that, the line uses both the function and these constants. This is what the constant looks like string
when printed to the console:
The sum of 5 and 100 is 105.
This mechanism can be especially useful when using the ternary operator , which allows you to check conditions when forming a string:
const age = 19
const message = `You can ${age < 21 ? 'not' : ''} view this page`
console.log(message)
The constant
message
printed to the console can change, depending on whether it is greater than or less than 21, the value stored in age
. Since this value is 19 in our example, the following will be sent to the console:
You can not view this page
Now you know how you can benefit from expression interpolation when using template literals. In the next section, we'll go further and explore tagging patterns, and talk about working with expressions passed in scopes that match placeholders.
Tag templates
Tag templates are an extended form of template literals. Tagged templates begin with a tagged function that parses the template literal, giving the developer more control over the dynamic string generation process.
In the following example, we create a function
tag
that we plan to use in the role of a function that performs operations on a tag template. The first named parameter to this function strings
is an array of string literals. Inline expressions are placed in the second parameter using the syntax of the remaining parameters . In order to see the contents of these parameters, they can be displayed in the console:
function tag(strings, ...expressions) {
console.log(strings)
console.log(expressions)
}
If you use a function when creating a tag template
tag
, you can get the following construction:
const string = tag`This is a string with ${true} and ${false} and ${100} interpolated inside.`
Since the function
tag
performs output to the console strings
and expressions
, when executing this code, the following will be sent to the console:
["This is a string with ", " and ", " and ", " interpolated inside."]
[true, false, 100]
You can see that the first parameter
strings
,, is an array containing all string literals:
"This is a string with "
" and "
" and "
" interpolated inside."
This argument also has a property
raw
that you can refer to as strings.raw
. It contains a line on which no escape sequences have been processed. For example, it \n
will be just a character \n
, not a line feed command.
The second argument,,
...expressions
is an array containing all expressions:
true
false
100
As a result, it appears that
tag
string literals and expressions are passed to the tag template function . Note that the function is not required to return a string. It can work with the values passed to it and return anything. For example, we might have a function that pays no attention to anything and just returns null
. This is how the function is written returnsNull
in the following example:
function returnsNull(strings, ...expressions) {
return null
}
const string = returnsNull`Does this work?`
console.log(string)
As a result of executing this code, the following will appear in the console:
null
As an example of what you can do in a tagged template, you can make changes to each of the expressions, such as changes to include expressions in HTML tags. Let's create a function
bold
that adds tags to <strong>
both </strong>
the beginning and the end of each expression:
function bold(strings, ...expressions) {
let finalString = ''
//
expressions.forEach((value, i) => {
finalString += `${strings[i]}<strong>${value}</strong>`
})
//
finalString += strings[strings.length - 1]
return finalString
}
const string = bold`This is a string with ${true} and ${false} and ${100} interpolated inside.`
console.log(string)
Here,
expressions
a forEach loop is used to traverse the array . Each element is enclosed in tags <strong></strong>
.
This is a string with <strong>true</strong> and <strong>false</strong> and <strong>100</strong> interpolated inside.
There are several examples of using tag templates in popular JavaScript libraries. For example, the graphql-tag library uses a template literal
gql
to parse GraphQL query strings and transform them into an abstract syntax tree (AST) that GraphQL understands:
import gql from 'graphql-tag'
// 5
const query = gql`
{
user(id: 5) {
firstName
lastName
}
}
`
The styled-components library also uses tagging functionality to create new React components from regular DOM elements and apply additional CSS styles to them :
import styled from 'styled-components'
const Button = styled.button`
color: magenta;
`
// <Button>
Alternatively, you can use the standard String.raw method to apply it to tagged templates to prevent the processing of escape sequences:
const rawString = String.raw`I want to write /n without it being escaped.`
console.log(rawString)
The following will appear in the console after executing this code:
I want to write /n without it being escaped.
Outcome
In this article, we remembered the basic information about ordinary string literals, formatted with single or double quotes, and also talked about template literals and tag templates. Template literals simplify many string-processing tasks. In particular, we are talking about embedding different values in strings and about creating multi-line strings without using concatenation or escaping. Tagging is a useful advanced template literal feature that is used in many popular libraries.
Do you use template literals?