How Lodash _.template Compiles Strings into Functions
Lodash’s _.template utility converts template strings
into reusable, executable JavaScript functions by parsing delimiter
syntax, transforming the text into dynamic JavaScript source code, and
evaluating that code using the Function constructor. This
article breaks down the step-by-step internal compilation pipeline used
by Lodash, covering regular expression parsing, source string
construction, variable scoping, and final function generation.
1. Delimiter Matching and Regular Expressions
The compilation process begins by analyzing the input string for specific delimiter patterns. By default, Lodash supports three types of template tags defined by configurable regular expressions:
- Interpolate (
<%= %>): Inserts the raw value of an expression directly into the output. - Escape (
<%- %>): Inserts the HTML-escaped value of an expression. - Evaluate (
<% %>): Executes arbitrary JavaScript logic (such as loops or conditional statements) without printing a value.
Lodash combines these patterns into a single master regular expression. As it scans the template string from left to right, it extracts static string segments and dynamic code tokens.
2. Building the Source String
Once the tokens are identified, Lodash constructs a raw JavaScript
code string. It initializes an output buffer variable—commonly named
__p internally—that accumulates the rendered text.
- Static Text: Plain text outside of delimiters is
escaped to prevent syntax errors (handling quotes, newlines, and
backslashes) and appended to the buffer:
__p += 'static text'; - Interpolation: Expressions wrapped in
<%= %>are converted into code that casts the evaluation to a string and appends it to the buffer:
__p += (expression == null ? '' : expression); - HTML Escaping: Expressions inside
<%- %>are wrapped in an internal escape helper (_.escape) before being appended:
__p += _.escape(expression); - Evaluation: Code inside
<% %>is injected directly into the generated source code without concatenation, allowing native JavaScript control flow:
if (condition) {
3. Handling Scope and Data Access
By default, template expressions expect to reference variables
directly (e.g., <%= user.name %>). To make this work,
Lodash wraps the generated body in a with statement:
with (obj || {}) {
// Generated template code
}Because with statements can hinder JavaScript engine
optimizations and are disallowed in strict mode, Lodash provides a
variable option (e.g., { variable: 'data' }).
Supplying this option tells Lodash to avoid using with and
instead prefix all internal property Lookups directly to the designated
parameter name, significantly improving execution performance.
4. Compiling via the
Function Constructor
After assembling the complete JavaScript source string, Lodash wraps it with standard function boilerplate:
function(data) {
var __p = '';
// ... assembled source code ...
return __p;
}It then passes the argument names and the source code string into the
native JavaScript Function constructor:
var compiled = new Function('data', '_', sourceString);This step compiles the string into machine code via the browser's or Node.js's Just-In-Time (JIT) compiler, returning a real, callable JavaScript function.
5. Returning the Executable Function
Lodash wraps this raw compiled function in a wrapper function that
automatically binds utility references (like _ for escaping
and custom imports). When the user invokes the returned function with a
data object, the JIT-compiled function executes synchronously and
returns the fully assembled output string.