字符串概述
字符串是表示文本数据的基本数据类型,在JavaScript中:
- 字符串是不可变的(immutable)
- 可以使用单引号、双引号或反引号创建
- 支持Unicode字符集
- 提供丰富的内置方法
- 支持模板字符串(ES6)
- 可以使用正则表达式进行复杂匹配
字符串创建
有多种方式可以创建字符串:
字符串创建
// 字符串字面量
let str1 = '单引号字符串';
let str2 = "双引号字符串";
let str3 = `模板字符串`;
// 字符串构造函数
let str4 = new String("字符串对象");
// 空字符串
let empty = "";
console.log(typeof str1); // "string"
console.log(typeof str4); // "object"
// 建议使用字面量而不是构造函数
字符串基本操作
访问字符
访问字符
let str = "Hello, World!";
// 使用索引访问字符
console.log(str[0]); // "H"
console.log(str[7]); // "W"
// 使用 charAt() 方法
console.log(str.charAt(0)); // "H"
console.log(str.charAt(7)); // "W"
// 访问不存在的索引
console.log(str[100]); // undefined
console.log(str.charAt(100)); // "" (空字符串)
// 获取字符编码
console.log(str.charCodeAt(0)); // 72 (H的Unicode编码)
字符串长度和遍历
字符串长度和遍历
let str = "JavaScript";
// 获取字符串长度
console.log(str.length); // 10
// 使用 for 循环遍历
for (let i = 0; i < str.length; i++) {
console.log(str[i]);
}
// 使用 for...of 循环遍历
for (let char of str) {
console.log(char);
}
// 转换为数组再遍历
let chars = str.split("");
chars.forEach(char => console.log(char));
字符串方法 - 搜索和检查
| 方法 | 描述 | 示例 | 返回值 |
|---|---|---|---|
indexOf() |
查找子串位置 | "hello".indexOf("l") |
2 |
lastIndexOf() |
从后向前查找 | "hello".lastIndexOf("l") |
3 |
includes() |
检查是否包含 | "hello".includes("ell") |
true |
startsWith() |
检查是否以某字符串开头 | "hello".startsWith("he") |
true |
endsWith() |
检查是否以某字符串结尾 | "hello".endsWith("lo") |
true |
search() |
使用正则表达式搜索 | "hello".search(/[aeiou]/) |
1 |
搜索和检查示例
let text = "Hello, JavaScript World!";
// indexOf() 和 lastIndexOf()
console.log(text.indexOf("Java")); // 7
console.log(text.lastIndexOf("o")); // 19
console.log(text.indexOf("Python")); // -1 (未找到)
// includes(), startsWith(), endsWith()
console.log(text.includes("JavaScript")); // true
console.log(text.startsWith("Hello")); // true
console.log(text.endsWith("World!")); // true
// 可以指定搜索的起始位置
console.log(text.includes("Java", 10)); // false (从位置10开始搜索)
// search() - 使用正则表达式
console.log(text.search("Java")); // 7
console.log(text.search(/[A-Z]/)); // 0 (第一个大写字母的位置)
字符串方法 - 提取和分割
| 方法 | 描述 | 示例 | 返回值 |
|---|---|---|---|
slice() |
提取子字符串 | "hello".slice(1, 4) |
"ell" |
substring() |
提取子字符串 | "hello".substring(1, 4) |
"ell" |
substr() |
提取子字符串 | "hello".substr(1, 3) |
"ell" |
split() |
分割字符串为数组 | "a,b,c".split(",") |
["a", "b", "c"] |
提取和分割示例
let text = "Hello, JavaScript!";
// slice(start, end) - 提取从start到end(不包括end)的子串
console.log(text.slice(7)); // "JavaScript!" (从位置7到末尾)
console.log(text.slice(7, 17)); // "JavaScript" (从位置7到17)
console.log(text.slice(-6)); // "Script!" (最后6个字符)
console.log(text.slice(-10, -1)); // "JavaScript"
// substring(start, end) - 类似slice,但不支持负数
console.log(text.substring(7)); // "JavaScript!"
console.log(text.substring(7, 17)); // "JavaScript"
// substr(start, length) - 从start开始提取length个字符
console.log(text.substr(7)); // "JavaScript!"
console.log(text.substr(7, 10)); // "JavaScript"
// split(separator, limit) - 分割字符串
let csv = "apple,banana,orange,grape";
console.log(csv.split(",")); // ["apple", "banana", "orange", "grape"]
console.log(csv.split(",", 2)); // ["apple", "banana"] (限制返回2个元素)
// 使用正则表达式分割
let sentence = "Hello World! How are you?";
console.log(sentence.split(/\s+/)); // ["Hello", "World!", "How", "are", "you?"]
注意:
substr()方法已不被推荐使用,建议使用slice()或substring()。
字符串方法 - 修改和转换
| 方法 | 描述 | 示例 | 返回值 |
|---|---|---|---|
toUpperCase() |
转换为大写 | "hello".toUpperCase() |
"HELLO" |
toLowerCase() |
转换为小写 | "HELLO".toLowerCase() |
"hello" |
trim() |
去除两端空格 | " hello ".trim() |
"hello" |
replace() |
替换子字符串 | "hello".replace("l", "x") |
"hexlo" |
concat() |
连接字符串 | "hello".concat(" ", "world") |
"hello world" |
repeat() |
重复字符串 | "hi".repeat(3) |
"hihihi" |
修改和转换示例
// 大小写转换
let text = "Hello World";
console.log(text.toUpperCase()); // "HELLO WORLD"
console.log(text.toLowerCase()); // "hello world"
// 去除空格
let spaced = " Hello World! ";
console.log(spaced.trim()); // "Hello World!"
console.log(spaced.trimStart()); // "Hello World! "
console.log(spaced.trimEnd()); // " Hello World!"
// 替换内容
let message = "I like cats. Cats are nice.";
console.log(message.replace("cats", "dogs")); // "I like dogs. Cats are nice."
console.log(message.replace(/cats/gi, "dogs")); // "I like dogs. Dogs are nice."
// 连接字符串
let hello = "Hello";
let world = "World";
console.log(hello.concat(", ", world, "!")); // "Hello, World!"
// 重复字符串
console.log("Ha".repeat(3)); // "HaHaHa"
console.log("*".repeat(10)); // "**********"
// 字符串填充
let num = "5";
console.log(num.padStart(3, "0")); // "005"
console.log(num.padEnd(3, "0")); // "500"
模板字符串 (ES6)
模板字符串使用反引号(`)创建,支持多行文本和表达式插值:
模板字符串
// 基本模板字符串
let name = "张三";
let age = 25;
let greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting); // "Hello, 张三! You are 25 years old."
// 多行字符串
let multiLine = `这是第一行
这是第二行
这是第三行`;
console.log(multiLine);
// 表达式计算
let a = 5, b = 10;
console.log(`${a} + ${b} = ${a + b}`); // "5 + 10 = 15"
// 函数调用
function double(x) {
return x * 2;
}
console.log(`双倍 ${a} 是 ${double(a)}`); // "双倍 5 是 10"
// 标签模板
function highlight(strings, ...values) {
let result = "";
strings.forEach((string, i) => {
result += string;
if (i < values.length) {
result += `<mark>${values[i]}</mark>`;
}
});
return result;
}
let highlighted = highlight`Hello ${name}, you are ${age} years old.`;
console.log(highlighted); // "Hello <mark>张三</mark>, you are <mark>25</mark> years old."
字符串和Unicode
JavaScript字符串使用UTF-16编码:
Unicode相关操作
// 基本Unicode字符
let heart = "❤";
let chinese = "中文";
let emoji = "😀";
console.log(heart.length); // 1
console.log(chinese.length); // 2
console.log(emoji.length); // 2 (某些emoji是代理对)
// 使用Unicode转义序列
let unicodeStr = "\u0048\u0065\u006C\u006C\u006F"; // "Hello"
let emojiStr = "\u{1F600}"; // "😀"
// 码点相关方法
let str = "😀";
console.log(str.codePointAt(0)); // 128512
console.log(String.fromCodePoint(128512)); // "😀"
// 正确处理Unicode的遍历
let specialStr = "❤😀中文";
// 错误的方式 (可能拆分代理对)
for (let i = 0; i < specialStr.length; i++) {
console.log(specialStr[i]);
}
// 正确的方式
for (let char of specialStr) {
console.log(char);
}
// 使用 Array.from()
let chars = Array.from(specialStr);
console.log(chars); // ["❤", "😀", "中", "文"]
字符串编码和解码
处理URL编码、Base64编码等:
编码和解码操作
// URL编码和解码
let url = "https://example.com/search?q=JavaScript 教程";
let encodedURL = encodeURI(url);
let decodedURL = decodeURI(encodedURL);
console.log(encodedURL); // "https://example.com/search?q=JavaScript%20%E6%95%99%E7%A8%8B"
console.log(decodedURL); // 原始URL
// 组件编码(更严格)
let component = "JavaScript 教程";
console.log(encodeURIComponent(component)); // "JavaScript%20%E6%95%99%E7%A8%8B"
// Base64编码和解码
let text = "Hello, World!";
let base64 = btoa(text); // 编码为Base64
let decoded = atob(base64); // 解码Base64
console.log(base64); // "SGVsbG8sIFdvcmxkIQ=="
console.log(decoded); // "Hello, World!"
// 处理Unicode的Base64编码
function unicodeBtoa(str) {
return btoa(unescape(encodeURIComponent(str)));
}
function unicodeAtob(str) {
return decodeURIComponent(escape(atob(str)));
}
let chineseText = "你好,世界!";
let chineseBase64 = unicodeBtoa(chineseText);
console.log(chineseBase64); // "5L2g5aW977yM5LiW55WM77yB"
console.log(unicodeAtob(chineseBase64)); // "你好,世界!"
字符串国际化
使用Intl API进行字符串本地化:
国际化字符串处理
// 字符串排序和比较
let words = ["ä", "z", "a"];
// 默认排序(基于Unicode码点)
console.log(words.sort()); // ["a", "z", "ä"]
// 使用本地化排序
let germanSorter = new Intl.Collator('de');
console.log(words.sort(germanSorter.compare)); // ["a", "ä", "z"]
// 字符串格式化
let date = new Date();
let formatter = new Intl.DateTimeFormat('zh-CN');
console.log(formatter.format(date)); // 本地化日期格式
// 数字格式化
let numberFormatter = new Intl.NumberFormat('zh-CN');
console.log(numberFormatter.format(1234567.89)); // "1,234,567.89"
// 相对时间格式化
let rtf = new Intl.RelativeTimeFormat('zh-CN');
console.log(rtf.format(-1, 'day')); // "1天前"
console.log(rtf.format(2, 'week')); // "2周后"
正则表达式与字符串
使用正则表达式进行复杂的字符串匹配和处理:
正则表达式应用
// 基本匹配
let text = "Hello, my email is example@email.com";
let emailRegex = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/;
let match = text.match(emailRegex);
console.log(match); // ["example@email.com"]
// 全局匹配
let words = "apple banana apple cherry";
let appleRegex = /apple/g;
let matches = words.match(appleRegex);
console.log(matches); // ["apple", "apple"]
// 替换操作
let phone = "Phone: 123-456-7890";
let formatted = phone.replace(/(\d{3})-(\d{3})-(\d{4})/, '($1) $2-$3');
console.log(formatted); // "Phone: (123) 456-7890"
// 验证格式
function isValidEmail(email) {
let emailRegex = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$/;
return emailRegex.test(email);
}
console.log(isValidEmail("test@example.com")); // true
console.log(isValidEmail("invalid-email")); // false
// 提取信息
function extractDomain(email) {
let domainRegex = /@([A-Za-z0-9.-]+\.[A-Z|a-z]{2,})/;
let match = email.match(domainRegex);
return match ? match[1] : null;
}
console.log(extractDomain("user@example.com")); // "example.com"
字符串性能优化
处理大量字符串时的性能优化技巧:
性能优化技巧
// 使用数组连接大量字符串
function buildStringEfficiently(strings) {
let result = [];
for (let i = 0; i < strings.length; i++) {
result.push(strings[i]);
}
return result.join('');
}
// 避免在循环中使用字符串连接
// 不好的做法
function buildStringInefficient(strings) {
let result = '';
for (let i = 0; i < strings.length; i++) {
result += strings[i]; // 每次都会创建新字符串
}
return result;
}
// 使用模板字符串的性能考虑
let name = "John";
let age = 30;
// 性能较好(字面量模板)
let message1 = `Hello, ${name}! You are ${age} years old.`;
// 性能较差(动态模板)
function createMessage(name, age) {
return `Hello, ${name}! You are ${age} years old.`;
}
// 使用字符串缓存
let stringCache = new Map();
function getCachedString(key, generator) {
if (!stringCache.has(key)) {
stringCache.set(key, generator());
}
return stringCache.get(key);
}
实践练习
👆 请点击上方按钮进行演示操作
选择不同的演示按钮来探索JavaScript字符串的各种功能和用法
最佳实践
- 优先使用模板字符串而不是字符串连接
- 使用
includes()而不是indexOf() !== -1检查包含 - 处理Unicode字符时使用
for...of或Array.from() - 使用
trim()清理用户输入 - 对于复杂的字符串操作,考虑使用正则表达式
- 避免使用
String构造函数,使用字面量 - 处理大量字符串时使用数组连接而不是直接连接
- 使用
IntlAPI进行本地化字符串处理