Day 7: 字符串操作
🎯 学习目标
- 掌握字符串的创建和基本操作
- 学会使用字符串方法进行转换和查找
- 理解字符串的不变性
- 掌握模板字符串的使用
- 学会处理常见的字符串操作场景
💡 核心概念
什么是字符串?
字符串是文本数据的序列,在 JavaScript 中用引号包围。
let str1 = "Hello"; // 双引号
let str2 = 'World'; // 单引号
let str3 = `Hello ${name}`; // 模板字符串
字符串的特性
- 不可变:字符串一旦创建不能修改
- 索引访问:可以通过索引访问单个字符
- 长度属性:
length返回字符数量
📝 创建字符串
1. 字符串字面量
// 单引号和双引号等价
let str1 = "Hello";
let str2 = 'Hello';
// 模板字符串(ES6)
let name = "张三";
let str3 = `你好,${name}`;
2. 转义字符
let str1 = "他说:\"你好\"";
let str2 = 'It\'s a cat';
let str3 = "第一行\n第二行"; // 换行
let str4 = "路径:C:\\Users"; // 反斜杠
let str5 = "版权:\u00A9"; // Unicode
3. 长字符串
// 使用 + 连接
let longStr = "这是第一行" +
"这是第二行" +
"这是第三行";
// 使用模板字符串(推荐)
let longStr2 = `这是第一行
这是第二行
这是第三行`;
🔍 字符串属性和方法
基本属性
let str = "Hello";
console.log(str.length); // 5
console.log(str[0]); // "H"
console.log(str[str.length-1]); // "o"
大小写转换
let str = "Hello World";
console.log(str.toUpperCase()); // "HELLO WORLD"
console.log(str.toLowerCase()); // "hello world"
// 首字母大写
let capitalize = str[0].toUpperCase() + str.slice(1).toLowerCase();
console.log(capitalize); // "Hello world"
查找和搜索
let str = "Hello World";
// indexOf() - 查找位置,不存在返回 -1
console.log(str.indexOf("World")); // 6
console.log(str.indexOf("world")); // -1(区分大小写)
console.log(str.indexOf("o")); // 4(第一个出现的位置)
// lastIndexOf() - 最后一次出现的位置
console.log(str.lastIndexOf("o")); // 7
// includes() - 是否包含
console.log(str.includes("World")); // true
console.log(str.includes("world")); // false
// startsWith() - 是否以...开头
console.log(str.startsWith("Hello")); // true
console.log(str.startsWith("World")); // false
// endsWith() - 是否以...结尾
console.log(str.endsWith("World")); // true
console.log(str.endsWith("Hello")); // false
// search() - 支持正则表达式
console.log(str.search(/World/i)); // 6(忽略大小写)
提取和截取
let str = "Hello World";
// charAt() - 获取指定位置的字符
console.log(str.charAt(0)); // "H"
// charCodeAt() - 获取字符的 Unicode 编码
console.log(str.charCodeAt(0)); // 72
// slice() - 提取子串(支持负数)
console.log(str.slice(0, 5)); // "Hello"
console.log(str.slice(6)); // "World"
console.log(str.slice(-5)); // "World"
console.log(str.slice(0, -6)); // "Hello"
// substring() - 提取子串(不支持负数)
console.log(str.substring(0, 5)); // "Hello"
// substr() - 已废弃,使用 slice 代替
替换和分割
let str = "Hello World";
// replace() - 替换(只替换第一个)
console.log(str.replace("World", "JavaScript")); // "Hello JavaScript"
// replaceAll() - 替换所有(ES2021)
console.log(str.replaceAll("l", "L")); // "HeLLo WorLd"
// 或使用正则表达式全局替换
console.log(str.replace(/l/g, "L")); // "HeLLo WorLd"
// split() - 分割字符串为数组
let str2 = "apple,banana,orange";
console.log(str2.split(",")); // ["apple", "banana", "orange"]
// 按空格分割
let str3 = "Hello World JavaScript";
console.log(str3.split(" ")); // ["Hello", "World", "JavaScript"]
// 按字符分割
console.log(str.split("")); // ["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d"]
去除空格
let str = " Hello World ";
// trim() - 去除首尾空格
console.log(str.trim()); // "Hello World"
// trimStart() / trimLeft() - 去除开头空格
console.log(str.trimStart()); // "Hello World "
// trimEnd() / trimRight() - 去除尾部空格
console.log(str.trimEnd()); // " Hello World"
// 使用正则去除所有空格
console.log(str.replace(/\s/g, "")); // "HelloWorld"
重复和填充
// repeat() - 重复字符串
console.log("Hi".repeat(3)); // "HiHiHi"
// padStart() - 开头填充
console.log("5".padStart(2, "0")); // "05"
console.log("1".padStart(5, "0")); // "00001"
// padEnd() - 尾部填充
console.log("5".padEnd(3, ".")); // "5.."
// 应用:格式化数字
let num = 42;
console.log(String(num).padStart(6, "0")); // "000042"
比较字符串
let str1 = "apple";
let str2 = "banana";
// 按字典序比较
console.log(str1 < str2); // true
console.log("a" < "b"); // true
console.log("A" < "a"); // true(大写字母的编码更小)
// localeCompare() - 本地化比较
console.log(str1.localeCompare(str2)); // -1(str1 在 str2 前面)
console.log("ä".localeCompare("z")); // -1(考虑本地规则)
🎨 模板字符串
基本用法
let name = "张三";
let age = 25;
// 插值
let str = `姓名:${name},年龄:${age}`;
console.log(str); // "姓名:张三,年龄:25"
// 表达式
let a = 10, b = 20;
console.log(`${a} + ${b} = ${a + b}`); // "10 + 20 = 30"
// 调用函数
function greet(name) {
return `Hello, ${name}!`;
}
console.log(`消息:${greet("张三")}`); // "消息:Hello, 张三!"
多行字符串
// 模板字符串支持多行
let html = `
<div>
<h1>标题</h1>
<p>段落</p>
</div>
`;
// 传统方式需要用 +
let html2 = "<div>" +
"<h1>标题</h1>" +
"<p>段落</p>" +
"</div>";
标签模板
function tag(strings, ...values) {
console.log(strings); // ["Hello ", "! ", ""]
console.log(values); // ["World", "JavaScript"]
return "Processed";
}
let result = tag`Hello ${"World"}! ${"JavaScript"}`;
console.log(result); // "Processed"
🎮 实战示例
示例1:用户名验证
function validateUsername(username) {
// 去除空格
username = username.trim();
// 检查长度
if (username.length < 3 || username.length > 20) {
return {valid: false, message: "用户名长度必须在 3-20 个字符"};
}
// 检查是否只包含字母、数字、下划线
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
return {valid: false, message: "用户名只能包含字母、数字、下划线"};
}
// 检查是否以字母开头
if (!/^[a-zA-Z]/.test(username)) {
return {valid: false, message: "用户名必须以字母开头"};
}
return {valid: true};
}
console.log(validateUsername("user123")); // {valid: true}
console.log(validateUsername("123user")); // {valid: false, message: "..."}
示例2:URL 构建
function buildURL(base, path, params) {
// 去除 base 的结尾 /
base = base.replace(/\/$/, "");
// 去除 path 的开头 /
path = path.replace(/^\//, "");
// 构建 URL
let url = `${base}/${path}`;
// 添加查询参数
if (params) {
let query = Object.keys(params)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
.join("&");
url += `?${query}`;
}
return url;
}
console.log(buildURL("https://api.example.com", "users", {page: 1, limit: 10}));
// "https://api.example.com/users?page=1&limit=10"
示例3:文件路径处理
function getFileName(path) {
// 获取最后一个 / 之后的内容
return path.slice(path.lastIndexOf("/") + 1);
}
function getFileExtension(filename) {
// 获取最后一个 . 之后的内容
return filename.slice(filename.lastIndexOf(".") + 1);
}
function getFilePath(filename) {
// 获取最后一个 / 之前的内容
return filename.slice(0, filename.lastIndexOf("/"));
}
let path = "/home/user/documents/file.txt";
console.log(getFileName(path)); // "file.txt"
console.log(getFileExtension(path)); // "txt"
console.log(getFilePath(path)); // "/home/user/documents"
示例4:文本格式化
function formatText(text) {
// 去除首尾空格
text = text.trim();
// 将多个连续空格替换为单个空格
text = text.replace(/\s+/g, " ");
// 首字母大写
text = text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
return text;
}
console.log(formatText(" hello world ")); // "Hello world"
示例5:生成随机字符串
function generateRandomString(length, charset) {
let result = "";
charset = charset || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < length; i++) {
result += charset.charAt(Math.floor(Math.random() * charset.length));
}
return result;
}
console.log(generateRandomString(10)); // "aB3xY9pQ2m"
console.log(generateRandomString(8, "ABCDEF123456")); // "3D1FA6C2"
示例6:驼峰命名转换
// 驼峰转短横线
function camelToKebab(str) {
return str.replace(/([A-Z])/g, "-$1").toLowerCase();
}
// 短横线转驼峰
function kebabToCamel(str) {
return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
}
// 驼峰转蛇形
function camelToSnake(str) {
return str.replace(/([A-Z])/g, "_$1").toLowerCase();
}
console.log(camelToKebab("backgroundColor")); // "background-color"
console.log(kebabToCamel("background-color")); // "backgroundColor"
console.log(camelToSnake("backgroundColor")); // "background_color"
✍️ 练习任务
练习1:统计字符出现次数
function countCharacters(str) {
let count = {};
for (let char of str) {
count[char] = (count[char] || 0) + 1;
}
return count;
}
console.log(countCharacters("hello"));
// {h: 1, e: 1, l: 2, o: 1}
练习2:反转字符串
function reverseString(str) {
return str.split("").reverse().join("");
}
console.log(reverseString("Hello")); // "olleH"
练习3:检查回文
function isPalindrome(str) {
// 去除空格和标点,转小写
str = str.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
// 反转比较
return str === str.split("").reverse().join("");
}
console.log(isPalindrome("A man, a plan, a canal: Panama")); // true
🎓 今日挑战
项目:Markdown 解析器
实现简单的 Markdown 转 HTML:
function parseMarkdown(markdown) {
let html = markdown;
# 标题
html = html.replace(/^# (.*$)/gim, "<h1>$1</h1>");
html = html.replace(/^## (.*$)/gim, "<h2>$1</h2>");
html = html.replace(/^### (.*$)/gim, "<h3>$1</h3>");
# 粗体和斜体
html = html.replace(/\*\*(.*?)\*\*/gim, "<b>$1</b>");
html = html.replace(/\*(.*?)\*/gim, "<i>$1</i>");
# 代码
html = html.replace(/`([^`]+)`/gim, "<code>$1</code>");
# 链接
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/gim, "<a href='$2'>$1</a>");
return html;
}
console.log(parseMarkdown("# Hello\n这是 **粗体** 和 *斜体*"));
💡 最佳实践
1. 优先使用模板字符串
// ✅ 好
let str = `Hello ${name}`;
// ❌ 差
let str = "Hello " + name;
2. 避免在循环中拼接字符串
// ❌ 不好(每次创建新字符串)
let str = "";
for (let i = 0; i < 1000; i++) {
str += i;
}
// ✅ 好用数组
let parts = [];
for (let i = 0; i < 1000; i++) {
parts.push(i);
}
let str = parts.join("");
3. 使用正则表达式处理复杂模式
// 验证邮箱
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
学习时间: 2026-03-08 03:05
难度: ⭐⭐⭐☆☆
预计用时: 2-3 小时
关键词: 字符串, 模板字符串, 正则表达式
相关标签: #05-字符串