JavaScript 模板字符串进阶:反引号转义、String.raw、标签模板

反引号转义

模板字符串用反引号包裹,内部出现反引号需要转义:

// 错误:会产生语法错误
const str = `hello `world``;

// 正确:用反斜杠转义
const str = `hello \`world\``;
// 输出:hello `world`

String.raw:禁止转义处理

String.raw 是内置标签函数,使反斜杠不被解释为转义字符:

// 普通模板:\n 被处理为换行
const a = `line1\nline2`;

// String.raw:\n 保持原样
const b = String.raw`line1\nline2`;
// 输出:line1\nline2(字面量)

适合场景:

// Windows 路径(不用写 \\)
const path = String.raw`C:\Users\admin\Desktop`;

// 正则(不用双重转义)
const pattern = new RegExp(String.raw`\d{4}-\d{2}-\d{2}`);

// Prompt / Python 代码片段
const prompt = String.raw`
请用 Python 处理:print("hello\nworld")
`;

数组 join:最稳的多行字符串

当内容包含大量特殊字符时,数组 join 完全避免转义问题:

const html = [
    '<script>',
    'console.log(`hello`)',
    '</script>'
].join('\n');

缺点是没有插值语法,需要手动拼接变量。

标签模板(Tagged Template)

模板字符串前加函数名即为标签模板,函数接收字符串片段和插值变量:

function highlight(strings, ...values) {
    return strings.reduce((result, str, i) =>
        result + str + (values[i] !== undefined ? `<b>${values[i]}</b>` : ''),
        ''
    );
}

const name = 'World';
const msg = highlight`Hello ${name}!`;
// 输出:Hello <b>World</b>!

标签模板的 strings.raw 属性包含未处理转义的原始字符串片段,这是 String.raw 的实现原理。

实际应用:

用途
styled-componentsCSS-in-JS
graphql-tag (gql)GraphQL 查询
lit-html (html)Web Components 模板
sql (SQL 防注入)参数化查询

外部文件替代超长模板

模板字符串不适合存放超长内容(HTML、SQL、Prompt)。更好的方式:

// Node.js:读取外部文件
const template = fs.readFileSync('./templates/email.html', 'utf8');

// Vite/Webpack:作为原始文本导入
import template from './templates/email.html?raw';

规则:代码逻辑放 JS,内容放文件,不要混在一起。