javaScript series [46]-tagged template

Posted by nonlinear on Wed, 05 Jan 2022 08:20:50 +0100

This paper introduces a special usage of template string, which allows us to follow a template string after the function name, and then pass various parts of the template string to the function in the form of parameters like normal function calls.

Tag template - tagged template It is not a real string template, but a special form of function call.

The tag in the tag template refers to the function, and the following template represents the actual parameters passed during the function call. If we have a function tag(){console.log(arguments)}, it will become a function call when the tag is followed by the template string.

function tag() {
    console.log(arguments);
}

let name = "Yong";
let age = 18;
tag `My name is ${name}. I'm ${age} years old`;

/* Printout */
/* 
[Arguments] {
  '0': [ 'My name is ', '. I\'m ', ' years old' ],
  '1': 'Yong',
  '2': 18 }
*/

Observe the above code and the corresponding execution results. During the call of the tag function, the template string part my name is ${name} I'm ${age} years old is split into different parts and passed to the function content in the form of parameters. Specifically, during splitting, all non variable parts (variable types refer to structures such as ${name}) will be passed in as the first parameter, and all variable data will be followed by the second, third and fourth Passed in as a parameter.

In order to distinguish and handle these two parameters more conveniently, we try to adjust the writing method of tag function by remaining parameters.

function tag(stringArr, ...args) {
    console.log("Part I:", stringArr);
    console.log("Part II:", args);
}

let name = "Yong";
let age = 18;
tag `My name is ${name}. I'm ${age} years old`;

/* Printout */
/* 
Part I: ['my name is',' I \'m ',' years old ']
Part II: ['Yong', 18]
*/

The writing of string double backquotes (we usually call it template string) is a new feature provided by ES6. As an enhanced version of string, this feature brings us at least two conveniences.

1. Convenient handling of line breaks in strings.
2. It is convenient to insert variables in the form of ${} in the string to replace the original + to complete the splicing.

Note: you can put any JavaScript expression in ${} of the template string, such as variable, ordinary string, simple calculation, reference object attribute and even function call. For details, please refer to the following demonstration code.

/* 1.Insert variable */
let address = "Guangzhou";
let str1 = `Address: ${ address }`;

/* 2.Insert number */
let str2 = `No.: ${ 10086 }`;

/* 3.Insert string */
let str3 = `Description: ${ 'description' }`;

/* 4.Simple calculation */
let x = 1,
    y = 5;
let str4 = `calculation: ${x} + ${y} * 2 == ${x + y * 2}`;

/* 5.function call */
let callFn = () => "callFn be Call";
let str5 = `Function call: ${callFn() }`;

/* 6.Test ternary operators */
let str6 = `Ternary operator: ${ 5>1 ?'The result is greater than 1':'The result is not greater than 1'}`;

/* Printout */
console.log(str1);
console.log(str2);
console.log(str3);
console.log(str4);
console.log(str5);
console.log(str6);
/* 
Address: Guangzhou
 No.: 10086
 Description: description
 Calculation: 1 + 5 * 2 = = 11
 Function call: callFn be Call
 Ternary operator: result greater than 1 */

It should be && natural for us to use the awesome feature of template string without thinking. However, I suggest to think more about the processing of backquote string. The following code encapsulates a function to simulate and restore the processing process.

function parse(strArr, ...args) {

    /* Print parameters */
    console.log('strArr = ', strArr);
    console.log('args   = ', args);

    let output = "";

    args.forEach((s, idx) => {
        console.log(`current - strArr[${idx}]`, strArr[idx]);
        output += strArr[idx] + s;
    })

    /* Because the number of args {variable parameters} will always be 1 more than the number of strArr, you need to splice the end */
    output += strArr[strArr.length - 1];

    return output;
}


let a = 1, b = 2;

/* Test code*/
console.log(parse `a = ${a} , b = ${b} , a + b = ${a + b} .`);

/* Printout  
strArr =  [ 'a = ', ' , b = ', ' , a + b = ', ' .' ]
args   =  [ 1, 2, 3 ]
current - strArr[0] a =
current - strArr[1]  , b =
current - strArr[2]  , a + b =
a = 1 , b = 2 , a + b = 3 .  
*/

In the above code, we complete the "restore" of the template string by using the parse function through the call structure of the label template.