JavaScript字符串不可变,所有方法返回新字符串;replace()需/g标志全局替换;includes()/startsWith()/endsWith()语义更清晰;模板字符串支持表达式但保留空白符。
JavaScript 字符串是原始类型、不可变的,所有方法(如 toUpperCase()、replace()、slice())都返回新字符串,不会修改原变量。常见错误是误以为 str.trim() 会改变 str 本身:
let str = " hello "; str.trim(); console.log(str); // 输出 " hello "
let str = " hello "; str = str.trim(); console.log(str); // 输出 "hello"
这个特性影响所有字符串操作——赋值或传参时必须显式接收返回值。
replace() 默认只处理第一个匹配,即使传入字符串字面量。想替换全部,必须用带 g 标志的正则表达式:
"aabbcc".replace("b", "x
"); // "aaxbcc"
"aabbcc".replace(/b/g, "x"); // "aaxxcc"
Invalid regular expression
动态构建正则时可用 new RegExp(pattern, "g"),但务必对 pattern 做转义处理(例如用 pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))。
过去常用 indexOf() !== -1 判断存在性,现在推荐语义更强、更安全的三个方法:
str.includes("foo") —— 是否包含子串(支持第二个参数:起始搜索位置)str.startsWith("Hello") —— 是否以某串开头(支持第二个参数:起始索引)str.endsWith("!") —— 是否以某串结尾(支持第二个参数:检查长度上限)它们不返回位置索引,避免了 0 和 -1 的真假混淆;且对空字符串行为明确(如 "abc".startsWith("") === true),而 indexOf("") 总是返回 0,容易引发逻辑 bug。
`Hello ${name || 'Guest'}` 比 "Hello " + (name || "Guest") 更简洁、无类型隐式转换风险。但要注意:
`a\nb` 真实包含换行符,不像多行字符串拼接那样需要手动加 \n
String.raw 或函数标签(如 stripIndent 类库),但原生不提供自动 trim 功能`She said: \`Hello\``
真正容易被忽略的是模板字符串的“标签函数”能力——它把插值前的静态部分和动态值分开传给函数,可用于 SQL 转义、国际化等场景,但多数人只当它是个高级拼接工具。