Tagged Template

A template literal may be untagged or tagged. Tags are functions that receive the contents of the provided template literal in two parts: the template object and the evaluated expressions. The template literals we saw so far are untagged, but we may optionally place a tag in front of a template literal.

Before you learn how to write your own tagged template functions, let’s make use of a built-in tagged template function called raw(). Suppose we want to create a string with some embedded special characters. In the next example we create a regular string, but by escaping each special character with a backslash.

 console.log(​'some special characters: ​​\​​ ​​\​​n ​​\​​b ​​'​​'​);

The output from this code is

 some special characters:  '

The string captures all the special characters in the output, but creating those characters required repetitive use of before each special character. Let’s try to remove those extra s and see how that goes.

 console.log(​"some special characters: ​​​​ ​​​​n ​​​​b '"​);

That’s less noisy. By using a double quotes, we were able to include the single quote with no backslash. That’s the only good part of this version. Getting rid of the backslash for other special characters, sadly, does not help, as we see from the output:

 some special characters:
  '

To achieve the desired result while keeping the code less noisy, instead of using a regular string in the previous version we can use a template literal and tag it with the String class’s raw() method. Let’s change the previous code to use template literals and the raw tag:

 console.log(String.raw​`some special characters:  '`​);

Even though a tag is written as a function, we do not invoke it like a function. Instead we tag a template literal by placing the tag literally in front of the template literal—no parentheses.

The string placed inside the template literal does not have extra backslashes. But the output created from this version is the same as the output from the first version where we used the extra backslashes:

 some special characters:  '

The raw tag is useful to get a raw form of string from a template literal. We can generalize the purpose of the tag from this example. A tag is useful to perform some special processing on a template literal. A tag does not have to return a string; it may return a string, a number, an object, or nothing at all.

Let’s see how to create a tag by writing a function that prints what it receives when used as a tag on a template literal.

 const​ printDetails = ​function​(texts, ...expressions) {
  console.log(texts);
  console.log(expressions);
 };
 
 const​ name = ​'John'​;
 printDetails​`Hello ​${name}​, how are you?`​;

The printDetails() function takes two parameters. texts is an array of all the string literals in the template literal. The second argument, expressions, is an array of all the evaluated expressions. When the printDetails() function is used as a tag on the given template literal, the texts array will hold two strings: the string part before the expression and the string part after the expression. The expressions array will hold one value: the result of the expression in the template literal given, ’John’ in this example. The tag function printDetails() does not return any result and that’s fine. Here’s the output for the code:

 [ 'Hello ', ', how are you?' ]
 [ 'John' ]

The length of the texts array will always be one more than the length of the expressions array. If a template literal is empty, then texts will hold one empty string. If a template literal has only one expression, then the value of the expression will be the single element in the expressions array, but the texts array will contain two empty strings—the empty string before the expression and the empty string after the expression.

A tag may be used to perform transformations on the given template literal. Here’s a tag that masks the expressions:

 const​ mask = ​function​(texts, ...expressions) {
 
 const​ createMask = (text) => ​'*'​.repeat(text.length);
 
 const​ maskedText = expressions
  .map((expression, index) =>
 `​${texts[index]}${createMask(expression.toString())}​`​)
  .join(​''​);
 const​ closingText = texts[texts.length - 1];
 
 return​ ​`​${maskedText}${closingText}​`​;
 };
 
 const​ agent = ​'Bond'​;
 const​ organization = ​'MI6'​;
 
 console.log(mask​`Hi, I'm ​${agent}​, with ​${organization}​.`​);

We iterate over the expressions array using the map() function and, for each expression, create a string of the text before the expression and a series of *s of the length of the value, converted to a string, in the expression. Finally we append to the result the string after the last expression in the template literal. The previous code produces the following output:

 Hi, I'm ****, with ***.

Try changing the template literal passed to the mask tag to different values—an empty template literal, one with no expressions, one with only expressions, expressions that are numbers, and so forth.

Since tags may transform template literals into various representations, the possibilities of its application is endless. Different JavaScript libraries may use tags for different purposes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.156.250