JavaScript / TypeScript 字符串方法
按“概念 -> 常用方法 -> 实战注意点”整理 String.prototype:查/取/改三类方法、常见混淆点、Unicode 坑。
[!info] related notes ECMAScript MOC ECMAScript正则表达式 JS 字符串:slice / substring / at / charAt 边界差异 JS 字符串:replace / replaceAll / 正则替换 JS 字符串与 Unicode:length、surrogate pair、正确拆分
JavaScript / TypeScript 字符串方法
1) 结论:JS 和 TS 的字符串方法几乎一样
TypeScript 没有发明新的字符串方法,只是给 JavaScript 的 String.prototype 加了类型标注。
const name: string = "hello";
const upper = name.toUpperCase(); // string
2) 字符串的本质:不可变(immutable)
字符串方法不会修改原字符串,而是返回新字符串。
let str = "hello";
str.toUpperCase();
console.log(str); // "hello"
str = str.toUpperCase();
console.log(str); // "HELLO"
3) 常用方法按三类记:查 / 取 / 改
3.1 查
- 有没有:
includes() - 在哪:
indexOf()/lastIndexOf() - 开头/结尾:
startsWith()/endsWith()
3.2 取
- 取字符:
at()/charAt()/[] - 取片段:
slice()(优先掌握)
3.3 改(返回新字符串)
- 替换:
replace()/replaceAll() - 大小写:
toUpperCase()/toLowerCase() - 去空格:
trim()/trimStart()/trimEnd() - 拆分:
split()
4) 长度和取字符
4.1 length(属性)
"hello".length; // 5
4.2 charAt / [] / at 的差异
const s = "hello";
s.charAt(100); // ""
s[100]; // undefined
s.at(-1); // "o" (supports negative index)
结论:现代代码里更常用 [] 和 at()。
更完整的差异表与例子:JS 字符串:slice / substring / at / charAt 边界差异。
5) 查找内容
5.1 includes vs indexOf
includes更像问“有没有”indexOf更像问“在哪”
const s = "hello world";
s.includes("world"); // true
s.indexOf("world"); // 6
5.2 search(正则)
只要是纯字符串查找,优先 includes/indexOf;需要正则再用 search。
"hello 123".search(/\d/); // 6
6) 截取字符串(重点)
6.1 slice(推荐)
特性:支持负数;语义更直观。
const s = "hello world";
s.slice(0, 5); // "hello"
s.slice(6); // "world"
s.slice(-5); // "world"
规则:包含 start,不包含 end。
6.2 substring(不支持负数 + 会交换)
const s = "hello";
s.substring(4, 1); // "ell"
s.slice(4, 1); // ""
6.3 substr(历史遗留,不推荐)
substr(start, length) 在新代码里尽量不要用了。
更完整的差异表与例子:JS 字符串:slice / substring / at / charAt 边界差异。
7) 替换
7.1 replace vs replaceAll
"a-b-c".replace("-", "_"); // "a_b-c"
"a-b-c".replaceAll("-", "_"); // "a_b_c"
"a-b-c".replace(/-/g, "_"); // "a_b_c"
7.2 replace 的函数替换(很实用)
const str = "hello world";
const result = str.replace(/\b\w+\b/g, (word) => word.toUpperCase());
// "HELLO WORLD"
更系统的 replace/replaceAll/捕获组:JS 字符串:replace / replaceAll / 正则替换。
8) 拆分与拼接
8.1 split
"a,b,c".split(",");
"hello".split("");
"a,b,c".split(",", 2);
8.2 concat
知道即可,现代项目更常用 + 或模板字符串。
9) 去空格
" hello ".trim();
" hello ".trimStart();
" hello ".trimEnd();
10) 正则相关:match / matchAll
match(/\d+/):第一个匹配match(/\d+/g):所有匹配(结构不同)matchAll():拿到所有匹配 + 捕获组 + 索引(迭代器)
更系统的正则笔记:ECMAScript正则表达式。
11) 编码与 Unicode 坑(面试/实战常问)
JavaScript 字符串底层是 UTF-16 编码单元序列:
length统计的是编码单元数量,不一定等于“用户看到的字符数”
"😊".length; // 2
相关方法:
charCodeAt(i):UTF-16 code unitcodePointAt(i):Unicode code point(处理 surrogate pair 更合理)
更系统的 Unicode 笔记:JS 字符串与 Unicode:length、surrogate pair、正确拆分。
12) TS 里的额外注意点
12.1 联合类型要先缩小
function print(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase());
}
}
12.2 字面量类型会变宽
const s = "hello"; // "hello"
const upper = s.toUpperCase(); // string
13) 常用方法速查表
| 类别 | 方法/属性 | 作用 |
|---|---|---|
| 长度 | length | 获取长度 |
| 取字符 | charAt() / at() / [] | 取字符 |
| 查找 | includes() | 是否包含 |
| 查找 | indexOf() / lastIndexOf() | 查位置 |
| 前后缀 | startsWith() / endsWith() | 判断前缀后缀 |
| 截取 | slice() / substring() | 截取子串 |
| 替换 | replace() / replaceAll() | 替换 |
| 大小写 | toUpperCase() / toLowerCase() | 转大小写 |
| 去空格 | trim() / trimStart() / trimEnd() | 去空白 |
| 拆分 | split() | 字符串转数组 |
| 正则 | match() / matchAll() / search() | 正则相关 |
| 编码 | charCodeAt() / codePointAt() | 编码 |
| 比较 | localeCompare() | 本地化比较 |
14) 优先掌握的 10 个
lengthincludesindexOfstartsWithendsWithslicereplacesplittrimtoUpperCase/toLowerCase