JavaScript模板引擎的核心能力是将包含变量、逻辑语法的模板字符串,转换为可执行的JavaScript函数,从而实现动态内容的渲染。整个过程主要分为模板解析、抽象语法树生成、代码生成三个核心步骤,每个步骤都有明确的职责划分。

模板解析阶段
模板解析的作用是将原始的模板字符串拆分成一个个独立的token,每个token对应模板中的不同内容,比如普通文本、变量占位符、逻辑指令等。比如对于模板字符串Hello {{name}}, age: {{age}},解析后会得到文本token、变量token、文本token、变量token的组合。
解析过程通常通过遍历模板字符串,匹配预设的语法规则来实现,常见的模板语法规则会用正则表达式来定义。下面是一个简单的解析示例:
// 定义匹配变量占位符的正则,匹配 {{ 和 }} 之间的内容
const variableReg = /{{([^}]+)}}/g;
function parseTemplate(templateStr) {
const tokens = [];
let lastIndex = 0;
let match;
// 循环匹配所有变量占位符
while ((match = variableReg.exec(templateStr)) !== null) {
// 如果占位符前面有普通文本,先添加文本token
if (match.index > lastIndex) {
tokens.push({
type: 'text',
value: templateStr.slice(lastIndex, match.index)
});
}
// 添加变量token,去除前后空格
tokens.push({
type: 'variable',
value: match[1].trim()
});
lastIndex = match.index + match[0].length;
}
// 处理最后剩余的普通文本
if (lastIndex < templateStr.length) {
tokens.push({
type: 'text',
value: templateStr.slice(lastIndex)
});
}
return tokens;
}
// 测试解析函数
const template = 'Hello {{name}}, age: {{age}}';
const tokens = parseTemplate(template);
console.log(tokens);
抽象语法树生成阶段
得到token列表后,需要将其转换为抽象语法树(AST),AST是模板结构的树形表示,能更清晰地体现模板的层级和逻辑关系。对于简单的模板,AST的节点通常分为文本节点和变量节点两类,每个节点包含自身的类型和对应的值。
生成AST的过程就是遍历token列表,将同类型的token归类,构建树形结构。上面的token列表转换后的AST结构如下:
const ast = [
{
type: 'text',
value: 'Hello '
},
{
type: 'variable',
value: 'name'
},
{
type: 'text',
value: ', age: '
},
{
type: 'variable',
value: 'age'
}
];
代码生成阶段
代码生成是模板引擎编译的核心环节,作用是将AST转换为可执行的JavaScript函数字符串,再通过new Function等方式将函数字符串转换为真正的函数。生成的函数在执行时,会接收数据对象作为参数,将模板中的变量替换为实际的值,最终返回渲染后的字符串。
代码生成的逻辑是遍历AST的每个节点,根据不同的节点类型拼接对应的代码片段:文本节点直接拼接字符串,变量节点拼接从数据对象中取对应值的代码。下面是具体的实现示例:
function generateCode(ast) {
let code = 'let result = "";n';
// 遍历AST节点拼接代码
ast.forEach(node => {
if (node.type === 'text') {
// 文本节点直接拼接字符串,注意转义单引号
code += `result += '${node.value.replace(/'/g, "\'")}';n`;
} else if (node.type === 'variable') {
// 变量节点拼接从数据对象取值的代码,假设数据对象参数名为data
code += `result += data.${node.value};n`;
}
});
code += 'return result;';
return code;
}
// 生成函数代码字符串
const functionCode = generateCode(ast);
console.log(functionCode);
// 将代码字符串转换为可执行函数
const renderFn = new Function('data', functionCode);
// 测试渲染函数
const data = { name: 'Tom', age: 18 };
const result = renderFn(data);
console.log(result); // 输出 Hello Tom, age: 18
处理复杂语法的扩展
实际的模板引擎还会支持条件判断、循环等复杂语法,这时候解析阶段需要识别对应的语法token,AST中会增加条件节点、循环节点等类型,代码生成阶段也需要对应拼接条件判断、循环的代码逻辑。比如支持{{if condition}}和{{/if}}语法的模板,解析时会识别if指令的开始和结束token,生成对应的条件AST节点,代码生成时就会拼接if (condition) { ... }的代码片段。
总结
JavaScript模板引擎的编译原理整体流程清晰,从模板字符串解析出token,再到生成AST,最后转换为可执行的渲染函数,每一步都是对模板结构的逐步抽象和转换。理解这个流程后,开发者不仅能更熟练地使用模板引擎,还能根据需求定制简单的模板引擎,处理特定的渲染场景。
JavaScript模板引擎代码生成编译原理修改时间:2026-07-13 11:51:25