javascript的模板字面量如何使用?【教程】

模板字面量是JavaScript中唯一原生支持多行字符串、表达式插值和标签函数的字符串语法,须用反引号包裹,${...}内表达式强制转字符串,null/undefined变为字面量,换行缩进需手动处理,String.raw可禁用转义序列。

模板字面量(template literal)不是“更高级的字符串拼接”,而是 JavaScript 中唯一能原生支持多行字符串、表达式插值和标签函数的字符串语法。用错地方或忽略细节,很容易掉进静默失败或安全漏洞的坑里。

怎么写一个基础模板字面量

必须用反引号 ` 包裹,不能用单引号或双引号。里面用 ${...} 插入任意表达式,包括变量、函数调用、甚至三元运算符。

`Hello ${name}, you have ${count || 0} new message${count === 1 ? '' : 's'}.`

注意:${...} 里的内容会强制转为字符串(调用 .toString()),但 nullundefined 会变成字面量字符串 "null""undefined",不是空字符串。

  • 别用 'Hello ${name}' —— 单引号下 ${name} 就是纯文本
  • ${} 内部不能有未声明变量,否则运行时报 ReferenceError
  • 如果只是想输出字面量 ${foo},得写成 $\{foo\}(用反斜杠转义)

换行和缩进怎么处理才不混乱

模板字面量天然支持换行,但缩进空格也会原样输出,容易让 HTML 或 JSON 输出带多余空白。

`
  

Hello ${name}

`

上面这段生成的 HTML 中,

前有两个空格, 前也有两个空格。解决方法:

  • .trim() 去首尾空白:htmlString.trim()
  • .replace(/\s+/g, ' ') 合并内部多余空白(慎用,会吃掉 pre 标签需要的空格)
  • 更稳妥的是把换行符和缩进逻辑写进模板里:`

    Hello ${name}

    `

为什么 String.raw 有时比普通模板字面量更安全

普通模板字面量会解析转义序列,比如 \n 变成换行符、\t 变成制表符。如果你在正则、文件路径或 SQL 片段里拼接字符串,这种自动解析可能破坏原始意图。

const path = `C:\temp\file.txt`; // 实际得到 "C:" + 换行 + "emp" + 制表符 + "ile.txt"
const rawPath = String.raw`C:\temp\file.txt`; // 正确得到字面量 "C:\\temp\\file.txt"

String.raw 是一个标签函数,它让模板字面量跳过所有反斜杠转

义处理。注意:它不阻止 ${...} 插值,只禁用转义序列解析。

  • 正则字面量中写 /\d+\.\d+/ 没问题,但拼接时用 new RegExp(`${prefix}\\d+\\.\\d+`) 容易漏掉双反斜杠
  • String.raw`...${prefix}...` 能避免手动加四层反斜杠
  • String.raw 不是模板字面量的“升级版”,而是不同用途的工具:一个用于人读友好的结构化字符串,一个用于机器精确的原始字节流

标签函数里 stringsvalues 到底是什么

自定义标签函数接收两个关键参数:strings(静态片段数组)和 values(插值表达式结果数组)。它们长度关系永远是 strings.length === values.length + 1

function highlight(strings, ...values) {
  let result = '';
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
    if (i < values.length) {
      result += `${values[i]}`;
    }
  }
  return result;
}

const name = 'Alice';
highlight`Hello ${name}! You're logged in.`;
// → ["Hello ", "! You're logged in."] 和 ["Alice"]

这个机制常被用于 CSS-in-JS 库(如 styled-components)、SQL 参数化(防止注入)、国际化(提取待翻译文本)等场景。但要注意:

  • strings 中的每个元素都已去除插值部分,且保留原始换行与空格
  • values 是运行时求值结果,不是源码字符串,所以无法做静态分析
  • 不要在标签函数里直接拼接用户输入到 HTML,仍需手动转义或使用 DOM API

模板字面量看着简单,但一旦涉及跨环境(Node.js / 浏览器 / Deno)、跨用途(HTML / SQL / CLI 命令)、跨信任边界(用户输入),那些默认行为就不再是“方便”,而是隐患源头。