JavaScript 字符串

字符串是表示文本的数据类型。网页上的所有文字、用户输入、API 返回的内容,基本都是字符串。这一章我们学习字符串的创建、查找、截取、替换、转换,重点掌握现代 JS 的模板字符串和常用的字符串方法。

1. 字符串与模板字符串

JS 字符串可以用单引号、双引号、反引号三种方式包裹。前两种几乎完全一样,反引号是 ES6 引入的模板字符串,功能更强大:

// 三种引号
const a = "双引号";
const b = '单引号';
const c = `反引号`;

// 模板字符串(反引号)的两大优势:

// 1. 嵌入变量和表达式:用 ${}
const name = "小明";
const age = 20;
const greeting = `你好,${name}!明年你 ${age + 1} 岁。`;
console.log(greeting);
// 输出: 你好,小明!明年你 21 岁。

// 2. 支持多行(单双引号不行)
const html = `<div>
  <h1>${name}</h1>
  <p>年龄:${age}</p>
</div>`;
console.log(html);

// 转义字符:反斜杠
console.log("换行\n 制表符\t 引号\" 反斜杠\\");

模板字符串的两个核心优势:多行书写嵌入表达式。现代 JS 中,需要拼接变量或多行文本时一律用反引号,告别 + 号拼接的繁琐。

2. 字符串是不可变的

字符串一旦创建,内容不能被修改。所有"修改"操作(如 replacetoUpperCase)都会返回新字符串,原字符串不变:

let s = "hello";
s[0] = "H";       // ⚠️ 无效!不会报错,但也没改变 s
console.log(s);    // "hello"

// 想改只能重新赋值
s = "H" + s.slice(1);
console.log(s);    // "Hello"

// 或者用 replace
s = s.replace("H", "h");
console.log(s);    // "hello"

3. 查找子串

// 查找子串
const str = "Hello, JavaScript!";

// indexOf:首次出现的位置(不存在返回 -1)
console.log(str.indexOf("Java"));     // 7
console.log(str.indexOf("Python"));   // -1

// lastIndexOf:最后一次出现的位置
console.log("a-b-c-d".lastIndexOf("-"));   // 5

// includes:是否包含(ES6,最直观)
console.log(str.includes("Java"));     // true
console.log(str.includes("java"));     // false(区分大小写)

// startsWith / endsWith:是否以某串开头/结尾
console.log(str.startsWith("Hello"));  // true
console.log(str.endsWith("!"));        // true

// 大小写无关的查找
console.log(str.toLowerCase().includes("java"));  // true

includes 是 ES6 引入的,语义最直观,日常开发优先用。需要知道位置时才用 indexOf。注意所有查找都区分大小写,需要忽略大小写就先 toLowerCase() 或用正则。

4. 截取子串

// 截取子串
const str = "Hello, World!";

// slice(起始, 结束):最推荐,支持负数
console.log(str.slice(7, 12));    // "World"(不含 end)
console.log(str.slice(7));        // "World!"(到末尾)
console.log(str.slice(-6, -1));   // "World"(负数从末尾算)

// substring(起始, 结束):类似 slice,但负数会变 0
console.log(str.substring(7, 12));  // "World"

// substr(起始, 长度):已废弃,不推荐
console.log(str.substr(7, 5));      // "World"

// charAt / charCodeAt
console.log(str.charAt(0));        // "H"
console.log(str.charCodeAt(0));    // 72(ASCII)
console.log(str[0]);               // "H"(也可以,但越界返回 undefined)

三个截取方法,记住 slice 就够了——它支持负数(从末尾算),行为最直观。substr 已被废弃,新代码不要用。

5. 大小写、空白、替换

const str = "Hello World";

// 大小写
console.log(str.toUpperCase());    // "HELLO WORLD"
console.log(str.toLowerCase());    // "hello world"

// trim():去掉首尾空白(常用!)
console.log("  hi  ".trim());      // "hi"
console.log("  hi  ".trimStart()); // "hi  "(只去首部)
console.log("  hi  ".trimEnd());   // "  hi"

// repeat():重复
console.log("ab".repeat(3));       // "ababab"

// padStart / padEnd:补齐到指定长度(格式化数字时超有用)
console.log("5".padStart(3, "0"));    // "005"
console.log("123".padEnd(6, "*"));    // "123***"

// replace / replaceAll:替换
console.log("hello".replace("l", "L"));      // "heLlo"(只换第一个)
console.log("hello".replaceAll("l", "L"));   // "heLLo"(换所有,ES2021)

trim 处理用户输入时几乎是必备——用户经常不小心多打个空格。padStart 在格式化数字(如日期、月份补零)时极其好用。

6. split 与 join

split 和 join 是字符串与数组之间的双向桥梁:

// split:字符串 → 数组(超常用)
const csv = "苹果,香蕉,樱桃";
const fruits = csv.split(",");
console.log(fruits);    // ["苹果","香蕉","樱桃"]

// 按空格切
console.log("hello world js".split(" "));
// ["hello","world","js"]

// 切成字符数组
console.log("abc".split(""));
// ["a","b","c"]

// 限制元素数量
console.log("1-2-3-4".split("-", 2));
// ["1","2"]

// 反向:join 把数组拼成字符串
console.log(["a", "b", "c"].join("-"));   // "a-b-c"

// 实战:URL 参数解析
const url = "name=小明&age=20";
const params = Object.fromEntries(
  url.split("&").map(pair => pair.split("="))
);
console.log(params);    // { name: "小明", age: "20" }

日常处理 CSV、URL 参数、分隔符数据,基本套路就是 split 成数组、操作、join 回字符串。

7. 字符串与正则表达式

JS 的正则表达式用 /模式/标志 写。字符串方法可以配合正则,实现复杂的匹配和替换:

// 字符串方法 + 正则
const str = "Hello 123 World 456";

// match:匹配
const nums = str.match(/\d+/g);
console.log(nums);    // ["123","456"]

// replace + 正则:全局替换
const result = str.replace(/\d+/g, "数字");
console.log(result);  // "Hello 数字 World 数字"

// test:测试是否匹配
console.log(/\d/.test("abc"));   // false
console.log(/\d/.test("a1"));    // true

// 实战:校验手机号(简单版)
function isPhone(s) {
  return /^1\d{10}$/.test(s);
}
console.log(isPhone("13812345678"));   // true
console.log(isPhone("12345"));         // false

// 实战:邮箱简单校验
function isEmail(s) {
  return /^[^@]+@[^@]+\.[^@]+$/.test(s);
}

正则是另一门大学问,这里只做入门。日常用得最多的场景是校验格式(手机号、邮箱、身份证)和批量替换。深入推荐看 MDN 正则教程。

8. 字符串与数字转换

// 字符串 ↔ 数字 转换

// 字符串 → 数字
console.log(Number("42"));      // 42
console.log(Number("42.5"));    // 42.5
console.log(Number(""));        // 0
console.log(Number("abc"));     // NaN
console.log(parseInt("42px"));  // 42(整数,会忽略小数点)
console.log(parseInt("3.99"));  // 3
console.log(parseFloat("3.14abc")); // 3.14
console.log(+"42");             // 42(最简写法)
console.log(Math.floor("3.99")); // 3

// 数字 → 字符串
console.log(String(42));        // "42"
console.log((42).toString());   // "42"
console.log((3.14159).toFixed(2)); // "3.14"(保留 2 位小数)
console.log((1234.5).toLocaleString()); // "1,234.5"(千分位)

parseFloat vs parseInt:前者保留小数,后者只取整数。Number vs parseInt:前者对非数字字符串返回 NaN,后者会"解析到第一个非数字字符"。

9. 编码与 Unicode

// JS 字符串内部是 UTF-16 编码
const cn = "你好";
console.log(cn.length);          // 2(两个字符)
console.log(cn.charCodeAt(0));   // 20320(Unicode 码点)

// 从码点创建字符
console.log(String.fromCharCode(20320));   // "你"

// 注意 emoji 是"代理对",length 不准
const emoji = "😀";
console.log(emoji.length);       // 2(实际是 1 个字符!)
console.log([...emoji].length);  // 1(用展开运算符获取真长度)

// Base64 编解码(浏览器内置)
const encoded = btoa("Hello");   // "SGVsbG8="
console.log(encoded);
console.log(atob(encoded));      // "Hello"

处理 emoji、特殊符号时,要小心 lengthsplit("")charAt 都可能不准。安全做法是用 [...str]Array.from(str) 转成"字符数组"。

10. 实战示例

// 1. 驼峰转下划线
function camelToSnake(s) {
  return s.replace(/[A-Z]/g, ch => "_" + ch.toLowerCase());
}
console.log(camelToSnake("userName"));    // "user_name"
console.log(camelToSnake("getUserInfo")); // "get_user_info"

// 2. 下划线转驼峰
function snakeToCamel(s) {
  return s.replace(/_([a-z])/g, (_, ch) => ch.toUpperCase());
}
console.log(snakeToCamel("user_name"));   // "userName"

// 3. 金额格式化:1234.5 → "1,234.50"
function formatMoney(n) {
  return n.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
console.log(formatMoney(1234.5));     // "1,234.50"

// 4. 截断长文本
function truncate(str, max) {
  return str.length > max ? str.slice(0, max - 1) + "…" : str;
}
console.log(truncate("hello world", 8));   // "hello w…"

小结

下一篇进入浏览器世界——DOM 操作,让 JS 真正能"动网页"。

← 上一篇 JavaScript 数组

下一篇 JavaScript DOM 操作

✈️💬