How JavaScript Tagged Template Literals Work
Tagged template literals are an advanced feature in JavaScript that allow functions to parse, process, and manipulate template strings. When a tag function is applied to a template literal containing variable substitutions, the JavaScript runtime splits the literal into an array of static string chunks and evaluates the dynamic expressions independently. The tag function then receives these components as distinct arguments, allowing custom logic to determine the final output.
The Mechanics of Evaluation
When JavaScript encounters a tagged template literal (e.g.,
tagFunction\Hello ${name}!``), it executes the evaluation
in a specific sequence:
- Expression Evaluation: The engine evaluates all
expressions inside the
${...}placeholders from left to right. - Static String Tokenization: The text surrounding
the expressions is partitioned into an array of string literals (a
TemplateStringsArray). - Function Invocation: The tag function is called. The static strings array is passed as the first argument, followed by each evaluated substitution as separate subsequent arguments.
Argument Structure
A tag function receives arguments matching this signature:
function tag(strings, ...values) {
// strings is an array of the static string parts
// values contains the evaluated results of each ${} expression
}If a template literal has \(N\)
expressions, the strings array will always contain \(N + 1\) elements. Even if an expression
appears at the very beginning or end of the literal, empty strings are
placed into the strings array to maintain this
consistency.
Step-by-Step Execution Example
Consider the following code:
function highlight(strings, ...values) {
return strings.reduce((accumulator, str, index) => {
const value = values[index] ? `<mark>${values[index]}</mark>` : '';
return `${accumulator}${str}${value}`;
}, '');
}
const item = 'laptop';
const price = 999;
const message = highlight`The ${item} costs $${price}.`;Here is how the engine processes the evaluation:
- Evaluate Substitutions: The variables
itemandpriceresolve to'laptop'and999. - Extract Static Strings: The engine splits the
static parts into
['The ', ' costs $', '.']. - Execute Tag Function: The
highlightfunction is called with:strings:['The ', ' costs $', '.']values:['laptop', 999]
- Return Value: The function iterates over the
strings and wraps dynamic values in
<mark>tags, returning:"The <mark>laptop</mark> costs $<mark>999</mark>.".
The strings.raw
Property
The first argument (strings) contains a special
.raw property. This property is an array containing the
exact strings as they were written, without interpreting escape
sequences (such as \n or \u00A9). This allows
tag functions to process raw text for domain-specific languages, regular
expressions, or shell commands.
String Immutability and Caching
The strings array passed to a tag function is frozen
using Object.freeze(), preventing mutation. In modern
JavaScript engines, identical tagged template literals in the same
source location share the same cached strings array
instance across multiple executions to optimize performance.