> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/web/js/val/prim/str/template-literal/tagged-template.md).

# tagged template

{% hint style="info" %}

* <mark style="color:yellow;">**Tagged templates**</mark> are [template literal](/web/js/val/prim/str/template-literal.md)s with a <mark style="color:purple;">**tag**</mark>.&#x20;
* They are **parsed** by its <mark style="color:purple;">**tag function**</mark>.&#x20;
  * The <mark style="color:yellow;">**first argument**</mark> of a tag function contains an <mark style="color:orange;">**array of strings**</mark>.&#x20;
  * The <mark style="color:yellow;">**remaining arguments**</mark> are related to the <mark style="color:orange;">**(interpolation) expressions**</mark>.
    {% endhint %}

{% tabs %}
{% tab title="🔴 Use Cases" %}

* [translation](https://javascript.plainenglish.io/template-literals-and-a-practical-use-of-tagged-templates-58526d525d72)
  {% endtab %}

{% tab title="💈例一" %}

```javascript
let person = 'Mike';
let age = 28;

// -------------------------
//     ⭐️ tagged template
// -------------------------
//           ╭tag╮  <-- tag function
//           │   │ ╭─0─╮         ╭─1──╮      2  <-- array of strings (p0)
let output = myTag`That ${person} is a ${age}.`;
//                      ╰──p1───╯      ╰─p2─╯   <-- interpolations (p1, p2 ...)

console.log(output);
// That Mike is a youngster.

// -----------------------
//     ⭐️ tag function
// -----------------------
//             ╭─arr─╮  ╭─interpolations─╮
function myTag(strings, personExp, ageExp ) {

    // manipulate array of strings
    let str0 = strings[0]; // "That "
    let str1 = strings[1]; // " is a "
    let str2 = strings[2]; // "."

    // manipulate interpolations
    let ageStr = ageExp > 99 ? 'centenarian' : 'youngster';

    return `${str0}${personExp}${str1}${ageStr}${str2}`;
}
```

{% endtab %}

{% tab title="💈例二" %}

```javascript
// 🌀 Array.prototype + .last
Object.assign(Array.prototype, {
    get last() { return this[this.length - 1] }
});

// -----------------------
//     ⭐️ tag function
// -----------------------

// `strings` and interpolated `values` are provided by the template literal
function template(strings, ...values) {
    // `args` are provided by the function parameters
    return (function (...args) {

        // last argument is expected to be an "options" objerct
        let opts = args.last || {};        // 🌀 Array.prototype + .last
        
        // reconstruct the "template" string (1/3)
        let result = [strings[0]];

        // for each interpolated value
        values.forEach((value, i) => {
            // if the value is number, choose from arguments,
            // otherwise, choose from the "options" object
            let selected = Number.isInteger(value) ? args[value] : opts[value];
            // reconstruct the "template" string (2/3)
            result.push(selected, strings[i + 1]);
        });

        // reconstruct the "template" string (3/3)
        return result.join('');
    });
}

// -------------------------
//     ⭐️ tagged templates
// -------------------------

template`${0}${1}${0}!`('Y', 'A'),                    // "YAY!"
// strings: ['', '', '', '!']
// values: [0, 1, 0] <----------- ⭐️ choose from `args`
// args: ['Y', 'A']
// opts: 'A' (ignored)

template`${0} ${'foo'}!`('Hello', { foo: 'World' }),   // "Hello World!"
// strings: ['', ' ', '!']
// values: [0, 'foo']  <-------------- ⭐️ choose from `args` & `opts`
// args: ['Hello', { foo: 'World' }]
// opts: { foo: 'World' }

//       ╭s0╮         ╭─── s1 ────╮        ╭── s2 ───╮  <-- strings
template`I'm ${'name'}. I'm almost ${'age'} years old.`({ name: 'MDN', age: 30 }),
//           ╰─ v0 ──╯             ╰─ v1 ─╯  <------- interpolated values
// result: "I'm MDN. I'm almost 30 years old."
// ---------------------------------------------
// strings: ["I'm ", ". I'm almost ", " years old."]
// values: ['name', 'age']  <----------- ⭐️ choose from `opts`
// args: [{ name: 'MDN', age: 30 }] (ignored)
// opts: { name: 'MDN', age: 30 }
```

{% endtab %}

{% tab title="📗 參考" %}

* [ ] [Template Literals and a Practical Use of Tagged Templates in JavaScript](https://javascript.plainenglish.io/template-literals-and-a-practical-use-of-tagged-templates-58526d525d72)
* [ ] (2020) JavaScript: The Definitive Guide (14.5 Creating DSLs (domain-specific languages) with template tag functions)
  {% endtab %}

{% tab title="📘 手冊" %}

* [tagged templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates)
  {% endtab %}

{% tab title="👥 相關" %}

* [destructuring assignment](/web/js/grammar/op/assign/destruct.md) is often used to manipulate interpolation parameters.
  {% endtab %}
  {% endtabs %}
