JavaScript 字符串与模板字符串
AI 辅助生成本文由 AI 起草并经人工核查,示例均标明软件版本;发现错误请以官方文档为准。
字符串处理几乎出现在每个脚本里:拼接输出、截取字段、清洗输入、生成模板。这一篇整理真正高频的方法。
三种引号
const a = "双引号";
const b = '单引号';
const c = `反引号(模板字符串)`;
前两者完全等价,用哪个取决于字符串里有没有引号字符:
const text = '他说:"你好"'; // 内部有双引号,外层用单引号
需要换行或多行文本时用模板字符串,普通引号里换行必须写 \n。
模板字符串
反引号里用 ${} 插入表达式:
const name = "ann";
const score = 95;
const msg = `${name} 的得分是 ${score}`;
console.log(msg); // "ann 的得分是 95"
${} 里是完整的表达式,不是只能放变量:
`合计:${orders.filter((o) => o.paid).length} 笔`;
`${score >= 60 ? "及格" : "不及格"}`;
`${(price * 1.13).toFixed(2)} 元`;
多行文本直接换行,缩进会被保留:
const html = `
<ul>
<li>${name}</li>
</ul>
`;
嵌套模板字符串要小心可读性,超过两层就该提取成变量。
字符串是不可变的
let s = "hello";
s[0] = "H";
console.log(s); // "hello",没有任何变化
所有「修改」方法都返回新字符串,原字符串不变:
const s = "hello";
s.toUpperCase(); // "HELLO",但 s 仍是 "hello"
const upper = s.toUpperCase();
长度与索引
const s = "hello";
s.length; // 5
s[0]; // "h"
s.at(-1); // "o",支持负索引(ES2022)
length 统计的是 UTF-16 码元,不是字符数。带 emoji 或某些生僻字时会“不准”:
"😀".length; // 2,一个 emoji 占两个码元
[... "😀"].length; // 1,展开后按码点统计
需要按「用户看到的一个字符」处理时,用展开 [...str] 或 Array.from(str) 转成数组。
查找与判断
const s = "hello world";
s.includes("world"); // true,是否包含
s.startsWith("he"); // true
s.endsWith("ld"); // true
s.indexOf("o"); // 4,首次出现位置,不存在返回 -1
s.lastIndexOf("o"); // 7,最后一次出现位置
判断存在用 includes(返回布尔),需要位置才用 indexOf。
截取:slice 与 substring
const s = "hello world";
s.slice(0, 5); // "hello"(含头不含尾)
s.slice(6); // "world"
s.slice(-5); // "world",支持负索引
s.substring(0, 5); // "hello"
两者差别:slice 支持负索引,且 start > end 时返回空串;substring 会把负索引当 0,且自动交换大小顺序。统一用 slice 即可。
替换
const s = "a-b-c";
s.replace("-", "/"); // "a/b-c",只替换第一个
s.replace(/-/g, "/"); // "a/b/c",正则 + g 标志替换全部
s.replaceAll("-", "/"); // "a/b/c",字符串参数也替换全部(ES2021)
replace 的字符串参数只替换第一处,这是最常见的坑。要替换全部,用 replaceAll 或带 g 标志的正则。
替换值是字符串时,$& 等有 special 含义,需要字面替换时用函数形式:
s.replaceAll("-", () => "/");
拆分与拼接
"a,b,c".split(","); // ["a", "b", "c"]
"a,b,c".split(",", 2); // ["a", "b"],限制返回个数
["a", "b"].join("-"); // "a-b"
["a", "b"].join(""); // "ab"
split 与 join 互为逆操作,是处理 CSV 风格文本的基础工具。
去空白与补齐
" hi ".trim(); // "hi",去两端空白
" hi ".trimStart(); // "hi "
" hi ".trimEnd(); // " hi"
"7".padStart(3, "0"); // "007"
"7".padEnd(3, "-"); // "7--"
trim 去除的空白包括空格、制表符和换行符,处理用户输入时几乎是必做的第一步。
大小写与重复
"Hello".toLowerCase(); // "hello"
"Hello".toUpperCase(); // "HELLO"
"-".repeat(3); // "---"
比较时统一大小写是常见做法:a.trim().toLowerCase() === b.trim().toLowerCase()。
一个完整例子:清洗用户输入
function normalizeTag(raw) {
return raw
.trim()
.toLowerCase()
.replaceAll(/\s+/g, "-")
.replaceAll(/[^a-z0-9一-龥-]/g, "");
}
normalizeTag(" Hello World "); // "hello-world"
normalizeTag("Node.js 22"); // "nodejs22"
常见错误与注意事项
replace("a", "b")只替换第一个:用replaceAll或/a/g。- 依赖
length当字符数:emoji 占两个码元,用[...str].length。 - 用
s[0] = "H"修改字符:字符串不可变,要生成新字符串。 substring传负索引:会被当成 0,用slice避免意外。- 模板字符串里嵌套过多表达式:可读性差,提取成变量再插入。
小结
- 模板字符串用
${}插入任意表达式,支持多行。 - 字符串不可变,所有修改方法返回新字符串。
- 判断存在用
includes,截取用slice,替换全部用replaceAll。 split/join是处理分隔文本的基本组合。