With a plethora of features that were ushered into the language in the ECMAScript 2015 (ES6), one of the most pragmatic feature that I find very commonly used is the template strings. Template literals are string literals allowing embedded expressions.
This allowed us to get rid of this somewhat clumsy syntax while creating a string using concatenation ,
const character = {
name: 'Din Djarin',
creed: 'Mandalorian',
dialogue: 'I can bring you in warm, or I can bring you in cold',
};
const sentence = character.name + ' is a ' + character.creed + ', and says "' + character.dialogue + '".';
console.log(sentence);
> Din Djarin is a Mandalorian, and says "I can bring you in warm, or I can bring you in cold".
With ES6 template literals we could create a string using a much cleaner syntax and it is something we have been using day in and day out.
const sentence = `${character.name} is a ${character.creed}, and says "${character.dialogue}".`;
console.log(sentence);
> Din Djarin is a Mandalorian, and says "I can bring you in warm, or I can bring you in cold".
A very powerful feature of template literals is that we can tag them, that means we can run the template string through a function rather than have them value immediately assigned. This description of tagged template literals may seem a bit obscure, let us try to understand this concept through examples.
The way the tag template works is you make a function that is going to process the string, and you take the name of the function that you want to run against the string, and you place the function name right in front of the template string.
const strongify = () => {
// do something
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
console.log(characterOneDescription);
> undefined
The output is undefined
instead of the complete string because the template string is processed by strongify
function and it does not return anything, that is the reason the variable characterOneDescription
is set to the value of undefined
.
Let's make the strongify
function return something.
const strongify = () => {
return 'Damn the tagged template literals are sick!';
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
console.log(characterOneDescription);
> Damn the tagged template literals are sick!
The function which with which we tag the string is called with the following arguments:
- An array comprising of all the string parts.
- Individual values as separate arguments.
Let's see this in code,
const strongify = (strings, value1, value2, value3) => {
console.log(`Inside strongify: ${strings}`);
console.log(`Inside strongify: ${value1}`);
console.log(`Inside strongify: ${value2}`);
console.log(`Inside strongify: ${value3}`);
return 'Character description: cool';
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
console.log(characterOneDescription);
> Inside strongify: , is , of the village ,
Inside strongify: Naruto
Inside strongify: Hokage
Inside strongify: Konoha
Character description: cool
Capturing the values as value1
, value2
... is not a very efficient way, therefore going forward we will use the ES6 rest operator to pack all the values into an array, so our code will look like this now,
const strongify = (strings, ...values) => {
console.log(`Inside strongify: ${strings}`);
console.log(`Inside strongify: ${values}`);
return 'Character description: cool';
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
console.log(characterOneDescription);
> Inside strongify: , is , of the village ,
Inside strongify: Naruto,Hokage,Konoha
Character description: cool
So we have received the following strings and values,
Strings | Values |
---|---|
'' | 'Naruto' |
' is ' | 'Hokage' |
'of the village' | 'Konoha' |
'' |
NOTE: There will be always one more string than value, while the function processes the template literal it will always start with a string and end with a string. Our template literal
characterOne
may seem to start and end with a value, in this case the parsing function treat the starting string and ending string as an empty string.
Let's try if we could process the entire string and render as it should without the tag, using a tagged function π
So we append the first item from string array with the first item from value array, and so on
const strongify = (strings, ...values) => {
let str = '';
strings.forEach((string, index) => (str += string + values[index]));
return str;
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
console.log(characterOneDescription);
> Naruto is Hokage of the village Konohaundefined
OOPS! we have four strings and three values (remember we will have one string more than the number of values), therefore we get this incorrect result. Let's fix this by using the OR operator default value pattern.
const strongify = (strings, ...values) => {
let str = '';
strings.forEach((string, index) => (str += string + (values[index] || '')));
return str;
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
console.log(characterOneDescription);
Naruto is Hokage of the village Konoha
This looks good, now we know how to tag strings with functions, but we haven't done anything different until now.
Suppose the characterOneDescription
is to be displayed on an HTML document and the values supplied to the template literal must indicate strong importance i.e. while displaying the template string the values must be wrapped in <strong>
tag.
Let's tweak our code
index.html
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<p id="character-description"></p>
<script src="./app.js"></script>
</body>
</html>
app.js
const strongify = (strings, ...values) => {
let str = '';
strings.forEach(
(string, index) =>
(str += `${string} <strong>${values[index] || ''}</strong>`)
);
return str;
};
const characterOne = {
name: 'Naruto',
rank: 'Hokage',
village: 'Konoha',
};
const characterOneDescription = strongify`${characterOne.name} is ${characterOne.rank} of the village ${characterOne.village}`;
const description = document.getElementById('character-description');
description.innerHTML = characterOneDescription;
The output is,
This was a very simple use case we tried out with the tagged template strings. There are much more complicated use cases for that. The main idea is this, if you have a template literal and want to process it programatically before it is assigned to a variable we can do that by tagging the template string with a function.
One very common use case is representing Windows file paths in our JavaScript files.
const filePath = `D:\Games\steamapps\common\Grand Theft Auto V`;
console.log(filePath);
> D:GamessteamappscommonGrand Theft Auto V
This is because the backslash indicates an escape character
in JavaScript, to fix that we have to escape
the back slash
const filePath = `D:\\Games\\steamapps\\common\\Grand Theft Auto V`;
console.log(filePath);
> D:\Games\steamapps\common\Grand Theft Auto V
To avoid having to escape
backslashes we can use the built-in String.raw()
static tag function for the template literals,
const filePath = String.raw`D:\Games\steamapps\common\Grand Theft Auto V`;
console.log(filePath);
D:\Games\steamapps\common\Grand Theft Auto V
Conclusion
So in this post we looked at how we can create tag functions to process template literals, and demonstrated how convenient it becomes to process strings using one of the built-in tag method.
Happy coding π
Top comments (0)