05-字符串处理方法
分类:01-JavaScript基础核心
发布于:
阅读时间:69 分钟
字符串处理方法
📋 学习目标
- 掌握JavaScript字符串的常用API
- 学会字符串的创建、访问、修改和转换方法
- 理解正则表达式与字符串的结合使用
- 掌握字符串性能优化技巧
🎯 字符串基础
1. 字符串创建方式
// 方法1:单引号
let str1 = 'Hello World';
// 方法2:双引号
let str2 = "Hello World";
// 方法3:模板字符串(ES6)
let name = 'Alice';
let age = 25;
let str3 = `My name is ${name} and I'm ${age} years old`;
// 方法4:String构造函数
let str4 = new String('Hello World');
// 注意:str4是对象类型,不是字符串原始类型
console.log(typeof str4); // 'object'
console.log(str4.valueOf()); // 'Hello World'
// 方法5:String函数(类型转换)
let num = 123;
let str5 = String(num); // '123'
2. 字符串长度和字符访问
let text = 'JavaScript';
// 获取字符串长度
console.log(text.length); // 10
// 访问字符(方法1:方括号)
console.log(text[0]); // 'J'
console.log(text[4]); // 'S'
// 访问字符(方法2:charAt)
console.log(text.charAt(0)); // 'J'
console.log(text.charAt(4)); // 'S'
// 获取字符编码
console.log(text.charCodeAt(0)); // 74 (J的ASCII码)
console.log(text.charCodeAt(4)); // 83 (S的ASCII码)
// 获取Unicode码点
console.log(text.codePointAt(0)); // 74
🔧 字符串查找方法
1. indexOf() 和 lastIndexOf()
let text = 'Hello JavaScript, Hello World';
// indexOf() - 从前向后查找
let index1 = text.indexOf('Hello'); // 0
let index2 = text.indexOf('Hello', 5); // 16 (从索引5开始查找)
let index3 = text.indexOf('Python'); // -1 (未找到)
// lastIndexOf() - 从后向前查找
let index4 = text.lastIndexOf('Hello'); // 16
let index5 = text.lastIndexOf('Hello', 10); // 0 (从索引10向前查找)
// 实际应用:判断字符串是否包含子串
function containsSubstring(str, substr) {
return str.indexOf(substr) !== -1;
}
console.log(containsSubstring(text, 'JavaScript')); // true
console.log(containsSubstring(text, 'Python')); // false
2. includes()、startsWith()、endsWith()(ES6)
let text = 'JavaScript is awesome';
// includes() - 判断是否包含子串
console.log(text.includes('Java')); // true
console.log(text.includes('java')); // false (区分大小写)
console.log(text.includes('Python')); // false
// startsWith() - 判断是否以子串开头
console.log(text.startsWith('Java')); // true
console.log(text.startsWith('Script')); // false
// endsWith() - 判断是否以子串结尾
console.log(text.endsWith('awesome')); // true
console.log(text.endsWith('some')); // false
// 实际应用:URL处理
function isExternalLink(url) {
return url.startsWith('http://') || url.startsWith('https://');
}
function isImageFile(filename) {
return filename.endsWith('.jpg') ||
filename.endsWith('.png') ||
filename.endsWith('.gif');
}
console.log(isExternalLink('https://example.com')); // true
console.log(isImageFile('photo.jpg')); // true
3. search() - 正则表达式查找
let text = 'The price is $123.45 for item [#123';](/tags/123';)
// 使用字符串
let index1 = text.search('$123'); // 14
// 使用正则表达式
let index2 = text.search(/\$\d+\.\d+/); // 14 (匹配价格模式)
let index3 = text.search(/#\d+/); // 29 (匹配编号模式)
// 区分大小写
let index4 = text.search(/javascript/i); // 0 (忽略大小写)
// 实际应用:邮箱验证
function isValidEmail(email) {
const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return pattern.test(email);
}
console.log(isValidEmail('user@example.com')); // true
console.log(isValidEmail('invalid-email')); // false
🔄 字符串转换方法
1. toUpperCase() 和 toLowerCase()
let text = 'JavaScript Programming';
// toUpperCase() - 转换为大写
let upperText = text.toUpperCase(); // 'JAVASCRIPT PROGRAMMING'
// toLowerCase() - 转换为小写
let lowerText = text.toLowerCase(); // 'javascript programming'
// 实际应用:忽略大小写的比较
function equalsIgnoreCase(str1, str2) {
return str1.toLowerCase() === str2.toLowerCase();
}
console.log(equalsIgnoreCase('Hello', 'hello')); // true
console.log(equalsIgnoreCase('JavaScript', 'JAVASCRIPT')); // true
// 实际应用:搜索时忽略大小写
function searchIgnoreCase(text, searchTerm) {
const lowerText = text.toLowerCase();
const lowerSearchTerm = searchTerm.toLowerCase();
return lowerText.includes(lowerSearchTerm);
}
console.log(searchIgnoreCase('JavaScript is fun', 'javascript')); // true
2. trim()、trimStart()、trimEnd()
let messyText = ' Hello World ';
// trim() - 去除两端空白
let trimmed = messyText.trim(); // 'Hello World'
// trimStart() / trimLeft() - 去除开头空白
let startTrimmed = messyText.trimStart(); // 'Hello World '
// trimEnd() / trimRight() - 去除结尾空白
let endTrimmed = messyText.trimEnd(); // ' Hello World'
// 实际应用:用户输入处理
function processUserInput(input) {
return input.trim(); // 去除用户输入的前后空白
}
console.log(processUserInput(' alice@example.com ')); // 'alice@example.com'
// 实际应用:CSV数据清理
let csvData = ' name, age, city ';
let cleanedData = csvData.trim().split(',').map(item => item.trim());
console.log(cleanedData); // ['name', 'age', 'city']
✂️ 字符串分割和连接
1. split() - 字符串分割
let text = 'apple,banana,orange,grape';
// 基本分割
let fruits = text.split(','); // ['apple', 'banana', 'orange', 'grape']
// 指定分割次数
let fruits2 = text.split(',', 2); // ['apple', 'banana']
// 使用正则表达式分割
let text2 = 'apple1banana2orange3grape';
let fruits3 = text2.split(/\d/); // ['apple', 'banana', 'orange', 'grape']
// 分割成字符
let text3 = 'hello';
let chars = text3.split(''); // ['h', 'e', 'l', 'l', 'o']
// 实际应用:URL参数解析
function parseQueryString(queryString) {
const params = {};
const pairs = queryString.substring(1).split('&');
pairs.forEach(pair => {
const [key, value] = pair.split('=');
params[decodeURIComponent(key)] = decodeURIComponent(value || '');
});
return params;
}
const url = '?name=Alice&age=25&city=New+York';
console.log(parseQueryString(url));
// { name: 'Alice', age: '25', city: 'New York' }
2. join() - 数组连接
let fruits = ['apple', 'banana', 'orange'];
// 基本连接
let text1 = fruits.join(); // 'apple,banana,orange'
// 指定分隔符
let text2 = fruits.join(', '); // 'apple, banana, orange'
let text3 = fruits.join(' | '); // 'apple | banana | orange'
// 空字符串连接
let text4 = fruits.join(''); // 'applebananaorange'
// 实际应用:CSV格式化
function formatCSV(data) {
return data.map(row => row.join(',')).join('\n');
}
const csvData = [
['Name', 'Age', 'City'],
['Alice', '25', 'New York'],
['Bob', '30', 'San Francisco']
];
console.log(formatCSV(csvData));
// "Name,Age,City\nAlice,25,New York\nBob,30,San Francisco"
📝 字符串提取方法
1. slice() - 字符串切片
let text = 'JavaScript Programming';
// 基本用法
let slice1 = text.slice(0, 10); // 'JavaScript'
let slice2 = text.slice(11); // 'Programming'
// 负索引
let slice3 = text.slice(-11); // 'Programming'
let slice4 = text.slice(-11, -4); // 'Program'
// 实际应用:截取文件扩展名
function getFileExtension(filename) {
const lastDotIndex = filename.lastIndexOf('.');
return lastDotIndex === -1 ? '' : filename.slice(lastDotIndex + 1);
}
console.log(getFileExtension('document.pdf')); // 'pdf'
console.log(getFileExtension('archive.tar.gz')); // 'gz'
2. substring() - 字符串子串
let text = 'JavaScript Programming';
// 基本用法
let substr1 = text.substring(0, 10); // 'JavaScript'
let substr2 = text.substring(11); // 'Programming'
// 参数交换(substring的特性)
let substr3 = text.substring(10, 0); // 'JavaScript' (自动交换参数)
// 负数处理(负数会被当作0)
let substr4 = text.substring(-5, 10); // 'JavaScript'
3. substr()(已废弃,不推荐使用)
let text = 'JavaScript Programming';
// substr(startIndex, length)
let substr1 = text.substr(0, 10); // 'JavaScript'
let substr2 = text.substr(11, 11); // 'Programming'
// 注意:substr已废弃,建议使用slice替代
🔄 字符串替换方法
1. replace() 和 replaceAll()
let text = 'Hello World, Hello Universe';
// replace() - 只替换第一个匹配项
let replaced1 = text.replace('Hello', 'Hi'); // 'Hi World, Hello Universe'
// 使用正则表达式(全局替换)
let replaced2 = text.replace(/Hello/g, 'Hi'); // 'Hi World, Hi Universe'
// replaceAll() - 替换所有匹配项(ES2021)
let replaced3 = text.replaceAll('Hello', 'Hi'); // 'Hi World, Hi Universe'
// 使用回调函数进行复杂替换
let text2 = 'The price is $123.45, total $246.90';
let replaced4 = text2.replace(/\$(\d+\.\d+)/g, (match, price) => {
const num = parseFloat(price);
return `$${(num * 1.1).toFixed(2)}`; // 价格上涨10%
});
console.log(replaced4); // 'The price is $135.80, total $271.59'
// 实际应用:模板变量替换
function replaceTemplate(template, data) {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data[key] || match;
});
}
const template = 'Hello {{name}}, you are {{age}} years old.';
const data = { name: 'Alice', age: 25 };
console.log(replaceTemplate(template, data));
// 'Hello Alice, you are 25 years old.'
2. 字符串填充方法(ES2017)
// padStart() - 开头填充
let num1 = '5';
let padded1 = num1.padStart(3, '0'); // '005'
let text1 = 'Hello';
let padded2 = text1.padStart(10, '*'); // '*****Hello'
// padEnd() - 结尾填充
let num2 = '5';
let padded3 = num2.padEnd(3, '0'); // '500'
let text2 = 'Hello';
let padded4 = text2.padEnd(10, '*'); // 'Hello*****'
// 实际应用:数字格式化
function formatNumber(num, width = 2) {
return String(num).padStart(width, '0');
}
console.log(formatNumber(5)); // '05'
console.log(formatNumber(123, 5)); // '00123'
// 实际应用:对齐文本
function alignText(text, width, align = 'left') {
switch(align) {
case 'left':
return text.padEnd(width);
case 'right':
return text.padStart(width);
case 'center':
const half = Math.floor((width - text.length) / 2);
return text.padStart(text.length + half).padEnd(width);
default:
return text;
}
}
console.log(alignText('Hello', 15, 'center')); // ' Hello '
🎯 高级字符串操作
1. 模板字符串高级用法
// 多行字符串
const multiline = `
This is a
multiline string
with easy formatting
`;
// 标签模板函数
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
const value = values[i] ? `<mark>${values[i]}</mark>` : '';
return result + str + value;
}, '');
}
const name = 'Alice';
const age = 25;
const highlighted = highlight`My name is ${name} and I'm ${age} years old`;
console.log(highlighted); // 'My name is <mark>Alice</mark> and I'm <mark>25</mark> years old'
// 实际应用:SQL查询构建
function sql(strings, ...values) {
return strings.reduce((query, str, i) => {
const value = values[i] !== undefined ? `'${values[i]}'` : '';
return query + str + value;
}, '');
}
const tableName = 'users';
const userId = 123;
const query = sql`SELECT * FROM ${tableName} WHERE id = ${userId}`;
console.log(query); // "SELECT * FROM 'users' WHERE id = '123'"
2. 字符串性能优化
// 字符串拼接性能比较
function testStringConcatenation() {
const iterations = 100000;
const str = 'hello';
// 方法1:使用 += (性能较差)
console.time('+= operator');
let result1 = '';
for (let i = 0; i < iterations; i++) {
result1 += str;
}
console.timeEnd('+= operator');
// 方法2:使用数组join (性能较好)
console.time('Array join');
const arr = [];
for (let i = 0; i < iterations; i++) {
arr.push(str);
}
const result2 = arr.join('');
console.timeEnd('Array join');
// 方法3:使用模板字符串 (现代JavaScript引擎优化)
console.time('Template literal');
let result3 = '';
for (let i = 0; i < iterations; i++) {
result3 = `${result3}${str}`;
}
console.timeEnd('Template literal');
}
// 字符串缓存优化
const stringCache = new Map();
function createTemplate(template, data) {
const cacheKey = JSON.stringify({ template, data });
if (stringCache.has(cacheKey)) {
return stringCache.get(cacheKey);
}
const result = template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data[key] || '';
});
stringCache.set(cacheKey, result);
return result;
}
3. Unicode和国际化
// 字符串长度计算(考虑Unicode)
function getUnicodeLength(str) {
return [...str].length;
}
const emoji = '👨👩👧👦';
console.log(emoji.length); // 11 (UTF-16代码单元)
console.log(getUnicodeLength(emoji)); // 1 (一个表情符号)
// 字符反转(支持Unicode)
function reverseString(str) {
return [...str].reverse().join('');
}
console.log(reverseString('hello')); // 'olleh'
console.log(reverseString('👋🌍')); // '🌍👋'
// 实际应用:用户名验证
function isValidUsername(username) {
// 支持Unicode字符的用户名验证
const pattern = /^[\p{L}\p{N}_]{3,20}$/u;
return pattern.test(username);
}
console.log(isValidUsername('用户123')); // true
console.log(isValidUsername('user_name')); // true
console.log(isValidUsername('a')); // false (太短)
⚠️ 常见陷阱
1. 字符串不可变性
let str = 'hello';
str[0] = 'H'; // ❌ 不会生效,字符串是不可变的
console.log(str); // 'hello'
// ✅ 正确的做法
str = 'Hello'; // 重新赋值
2. 中文字符处理
// 中文字符在UTF-8中占用多个字节
let chinese = '你好';
console.log(chinese.length); // 2 (JavaScript字符数)
console.log(new Blob([chinese]).size); // 6 (字节数)
// 正确的截取方式(避免截断中文字符)
function safeSubstring(str, maxLength) {
let result = '';
let length = 0;
for (const char of str) {
if (length + 1 > maxLength) break;
result += char;
length++;
}
return result;
}
console.log(safeSubstring('你好世界', 2)); // '你好'
3. 正则表达式特殊字符
// 需要转义的特殊字符
const specialChars = /[.*+?^${}()|[\]\\]/g;
function escapeRegExp(string) {
return string.replace(specialChars, '\\$&');
}
const userInput = '(hello)';
const pattern = new RegExp(escapeRegExp(userInput));
console.log(pattern.test('(hello)')); // true
📝 最佳实践
- 优先使用模板字符串:比字符串拼接更清晰
- 合理使用includes():比indexOf() !== -1更语义化
- 处理用户输入:始终使用trim()清理输入
- 考虑国际化:处理多语言字符时要小心
- 性能优化:大量字符串操作时考虑使用数组join
🎯 小结
- 掌握了JavaScript字符串的常用API
- 学会了字符串的创建、访问、修改和转换方法
- 理解了正则表达式与字符串的结合使用
- 掌握了字符串性能优化技巧
- 了解了Unicode处理和国际化注意事项
下一步学习:正则表达式详解