JavaScript字符串方法指南:从基础操作到实战应用
什么是字符串?
在JavaScript中,字符串是一系列字符的,可以包含字母、数字、符号以及特殊字符(如换行符\n、制表符\t等)。字符串是编程中最常用的数据类型之一,用于表示文本信息。
// 字符串的几种表示方式
let name = '张三'; // 单引号
let message = "Hello World"; // 双引号
let template = `年龄:${25}`; // 模板字符串(ES6)
let number = "12345"; // 数字字符串
let special = "换行符:\n新行"; // 包含特殊字符
创建字符串的两种方式:
// 1. 字符串字面量(推荐)
let str1 = 'JavaScript';
// 2. 字符串对象(不推荐,除非特殊需要)
let str2 = new String('JavaScript');
console.log(typeof str1); // string
console.log(typeof str2); // object
个人经验:日常开发中始终使用字符串字面量,除非你需要使用字符串对象的一些特殊特性。字面量更简洁,性能也更好。
常用字符串方法详解
1. charAt() - 获取指定位置的字符
返回字符串中指定索引位置的字符。
let str = 'JavaScript编程语言';
// 获取索引2的字符
console.log(str.charAt(2)); // v
console.log(str[2]); // v(现在写法,更简洁)
// 索引超出范围时
console.log(str.charAt(100)); // ''(空字符串)
console.log(str[100]); // undefined
// 遍历字符串中的每个字符
for (let i = 0; i < str.length; i++) {
console.log(`索引${i}: ${str.charAt(i)}`);
}
注意:charAt()和方括号[]的主要区别在于处理越界索引时的返回值不同。方括号语法是ES5引入的更现在的方式。
2. concat() - 拼接字符串
将一个或多个字符串与原字符串拼接,返回新字符串。
let hello = '你好';
let name = '张三';
let punctuation = '!';
// 使用concat拼接
let message1 = hello.concat(' ', name, punctuation);
console.log(message1); // '你好 张三!'
// 更常见的写法(使用+运算符)
let message2 = hello + ' ' + name + punctuation;
console.log(message2); // '你好 张三!'
// 模板字符串(ES6,推荐)
let message3 = `${hello} ${name}${punctuation}`;
console.log(message3); // '你好 张三!'
// 实际应用:构建SQL语句(需要谨慎处理SQL注入)
let tableName = 'users';
let condition = 'age > 18';
let query = 'SELECT * FROM '.concat(tableName, ' WHERE ', condition);
console.log(query); // 'SELECT * FROM users WHERE age > 18'
个人建议:在日常开发中,我很少使用concat()方法。字符串拼接用+运算符更简洁,而复杂的字符串构建用模板字符串最直观。
3. indexOf() - 查找子串位置
返回指定子串在原字符串中首次出现的索引,找不到返回-1。
let sentence = 'JavaScript是一门编程语言,JavaScript非常强大';
// 基本使用
console.log(sentence.indexOf('编程')); // 10
console.log(sentence.indexOf('Java')); // 0
console.log(sentence.indexOf('Python')); // -1
// 指定开始搜索的位置
console.log(sentence.indexOf('JavaScript', 5)); // 15(从索引5开始找)
// 实际应用:检查字符串是否包含特定内容
function containsKeyword(text, keyword) {
return text.indexOf(keyword) !== -1;
}
console.log(containsKeyword(sentence, '编程')); // true
console.log(containsKeyword(sentence, 'Python')); // false
// 统计某个词出现的次数
function countOccurrences(text, word) {
let count = 0;
let position = text.indexOf(word);
while (position !== -1) {
count++;
position = text.indexOf(word, position + 1);
}
return count;
}
console.log(countOccurrences(sentence, 'JavaScript')); // 2
4. lastIndexOf() - 从后查找子串位置
返回指定子串在原字符串中之后一次出现的索引。
let sentence = 'JavaScript是一门编程语言,JavaScript非常强大';
console.log(sentence.lastIndexOf('JavaScript')); // 15
console.log(sentence.lastIndexOf('编程')); // 10
console.log(sentence.lastIndexOf('Python')); // -1
// 指定结束搜索的位置(从开头到指定索引)
console.log(sentence.lastIndexOf('JavaScript', 10)); // 0(只搜索前10个字符)
// 实际应用:获取文件扩展名
function getFileExtension(filename) {
let lastDotIndex = filename.lastIndexOf('.');
if (lastDotIndex === -1) return ''; // 没有扩展名
return filename.slice(lastDotIndex + 1);
}
console.log(getFileExtension('document.pdf')); // 'pdf'
console.log(getFileExtension('photo.jpg')); // 'jpg'
console.log(getFileExtension('archive.tar.gz')); // 'gz'(注意:只取之后一个点后面的)
5. toLowerCase() 和 toUpperCase() - 大小写转换
将字符串中的所有字母转换为小写或大写。
let mixed = 'JavaScript Is AWESOME! 123';
// 转小写
let lower = mixed.toLowerCase();
console.log(lower); // 'javascript is awesome! 123'
// 转大写
let upper = mixed.toUpperCase();
console.log(upper); // 'JASCRIPT IS AWESOME! 123'
// 原字符串不变
console.log(mixed); // 'JavaScript Is AWESOME! 123'
// 实际应用:不区分大小写的比较
function compareIgnoreCase(str1, str2) {
return str1.toLowerCase() === str2.toLowerCase();
}
console.log(compareIgnoreCase('Hello', 'HELLO')); // true
console.log(compareIgnoreCase('Java', 'JavaScript')); // false
// 实际应用:首字母大写
function capitalizeFirst(str) {
if (!str) return '';
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}
console.log(capitalizeFirst('javaSCRIPT')); // 'Javascript'
console.log(capitalizeFirst('hello world')); // 'Hello world'
6. split() - 分割字符串
根据指定的分隔符将字符串拆分成数组。
let str = '苹果,香蕉,橙子,葡萄,西瓜';
// 基本分割
let fruits = str.split(',');
console.log(fruits); // ['苹果', '香蕉', '橙子', '葡萄', '西瓜']
// 限制返回数量
let limited = str.split(',', 3);
console.log(limited); // ['苹果', '香蕉', '橙子']
// 分割每个字符
let chars = 'Hello'.split('');
console.log(chars); // ['H', 'e', 'l', 'l', 'o']
// 使用正则表达式分割
let text = 'Hello1World2JavaScript';
let parts = text.split(/\d/); // 按数字分割
console.log(parts); // ['Hello', 'World', 'JavaScript']
// 实际应用:解析CSV数据
let csvLine = '张三,25,北京,工程师';
let userData = csvLine.split(',');
console.log('姓名:', userData[0]); // '张三'
console.log('年龄:', userData[1]); // '25'
console.log('城市:', userData[2]); // '北京'
// 实际应用:解析URL参数
function parseQueryString(queryString) {
if (!queryString) return {};
return queryString
.split('&')
.map(pair => pair.split('='))
.reduce((params, [key, value]) => {
params[key] = decodeURIComponent(value || '');
return params;
}, {});
}
let query = 'name=张三&age=25&city=北京';
console.log(parseQueryString(query));
// { name: '张三', age: '25', city: '北京' }
7. slice() - 提取子串
提取字符串的一部分并返回新字符串,支持负数索引。
let str = 'JavaScript编程语言';
// 基本用法:slice(start, end) - 从start到end(不包括end)
console.log(str.slice(0, 4)); // 'Java'
console.log(str.slice(4, 10)); // 'Script'
// 只指定起始位置
console.log(str.slice(4)); // 'Script编程语言'
// 负数索引(从末尾开始计数)
console.log(str.slice(-3)); // '语言'
console.log(str.slice(-6, -3)); // '编程'
// 实际应用:截取邮箱用户名
function getEmailUsername(email) {
let atIndex = email.indexOf('@');
if (atIndex === -1) return email;
return email.slice(0, atIndex);
}
console.log(getEmailUsername('zhangsan@example.com')); // 'zhangsan'
// 实际应用:截取文件路径中的文件名
function getFileName(filePath) {
let lastSlash = filePath.lastIndexOf('/');
if (lastSlash === -1) return filePath;
return filePath.slice(lastSlash + 1);
}
console.log(getFileName('/users/documents/report.pdf')); // 'report.pdf'
8. substring() - 另一种提取子串的方法
与slice类似,但不支持负数索引,且会自动调整参数顺序。
let str = 'JavaScript编程语言';
// 基本用法
console.log(str.substring(0, 4)); // 'Java'
console.log(str.substring(4, 10)); // 'Script'
// 自动调整顺序:如果start > end,会交换它们
console.log(str.substring(10, 4)); // 'Script'(等同于substring(4,10))
// 负数被视为0
console.log(str.substring(-5, 4)); // 'Java'(-5被视为0)
// slice和substring的区别
let = 'Hello World';
// 负数索引
console.log(.slice(-5)); // 'World'
console.log(.substring(-5)); // 'Hello World'(-5被视为0)
// start > end
console.log(.slice(6, 0)); // ''(返回空字符串)
console.log(.substring(6, 0)); // 'Hello'(自动交换为0,6)
个人建议:我倾向于使用slice(),因为它支持负数索引且行为更可预测。只有在需要自动参数交换这个特性时才考虑使用substring()。
9. substr() - 从指定位置提取指定长度的子串
let str = 'JavaScript编程语言';
// substr(start, length) - 从start开始,提取length个字符
console.log(str.substr(0, 4)); // 'Java'
console.log(str.substr(4, 6)); // 'Script'
// 只指定start
console.log(str.substr(4)); // 'Script编程语言'
// 负数start
console.log(str.substr(-3)); // '语言'
console.log(str.substr(-6, 3)); // '编程'
// 实际应用:截取定长字符串
function truncate(text, maxLength) {
if (text.length <= maxLength) return text;
return text.substr(0, maxLength) + '...';
}
console.log(truncate('这是一段很长的文本内容', 8)); // '这是一段很...'
注意:substr()是一个遗留方法,不推荐在新代码中使用。建议使用slice()或substring()作为替代。
更多字符串方法
10. trim() - 去除两端空白
let str = ' Hello World ';
console.log(`"${str}"`); // " Hello World "
console.log(`"${str.trim()}"`); // "Hello World"
// 只去除左侧空白
console.log(`"${str.trimStart()}"`); // "Hello World "
console.log(`"${str.trimLeft()}"`); // "Hello World "(别名)
// 只去除右侧空白
console.log(`"${str.trimEnd()}"`); // " Hello World"
console.log(`"${str.trimRight()}"`); // " Hello World"(别名)
// 实际应用:处理用户输入
function processUserInput(input) {
let cleaned = input.trim();
if (cleaned === '') {
return '输入不能为空';
}
return cleaned;
}
console.log(processUserInput(' 张三 ')); // '张三'
console.log(processUserInput(' ')); // '输入不能为空'
11. replace() - 替换子串
let str = '我喜欢JavaScript,JavaScript很有趣';
// 只替换第一个匹配项
let replaced1 = str.replace('JavaScript', 'Python');
console.log(replaced1); // '我喜欢Python,JavaScript很有趣'
// 使用正则表达式全局替换
let replaced2 = str.replace(/JavaScript/g, 'Python');
console.log(replaced2); // '我喜欢Python,Python很有趣'
// 使用函数进行动态替换
let replaced3 = str.replace(/JavaScript/g, (match, offset) => {
return offset === 0 '前端开发' : '编程';
});
console.log(replaced3); // '我喜欢前端开发,编程很有趣'
// 实际应用:敏感词过滤
function censor(text, badWords) {
let result = text;
badWords.forEach(word => {
let regex = new RegExp(word, 'gi');
result = result.replace(regex, '*'.repeat(word.length));
});
return result;
}
let comment = '这个网站太垃圾了,管理员是笨蛋';
let filtered = censor(comment, ['垃圾', '笨蛋']);
console.log(filtered); // '这个网站太**了,管理员是**'
12. includes() - 检查是否包含子串(ES6)
let str = 'JavaScript编程语言';
console.log(str.includes('Java')); // true
console.log(str.includes('Python')); // false
console.log(str.includes('Script', 4)); // true(从索引4开始检查)
// 实际应用:搜索过滤
let products = [
'iPhone手机',
'华为手机',
'小米平板',
'联想电脑'
];
function searchProducts(keyword) {
return products.filter(product =>
product.includes(keyword)
);
}
console.log(searchProducts('手机')); // ['iPhone手机', '华为手机']
console.log(searchProducts('电脑')); // ['联想电脑']
13. startsWith() 和 endsWith() - 检查开头和结尾(ES6)
let url = 'https://example.com/index.html';
console.log(url.startsWith('https')); // true
console.log(url.startsWith('http')); // false
console.log(url.startsWith('example', 8)); // true(从索引8开始检查)
console.log(url.endsWith('.html')); // true
console.log(url.endsWith('.php')); // false
console.log(url.endsWith('example', 16)); // true(只考虑前16个字符)
// 实际应用:URL协议检查
function isSecureUrl(url) {
return url.startsWith('https://');
}
console.log(isSecureUrl('https://google.com')); // true
console.log(isSecureUrl('http://example.com')); // false
// 实际应用:文件类型过滤
function isImageFile(filename) {
return filename.endsWith('.jpg') ||
filename.endsWith('.png') ||
filename.endsWith('.gif');
}
console.log(isImageFile('photo.jpg')); // true
console.log(isImageFile('document.pdf')); // false
14. repeat() - 重复字符串(ES6)
let str = '哈';
console.log(str.repeat(3)); // '哈哈哈'
console.log('='.repeat(10)); // '=========='
console.log('*'.repeat(5)); // '*****'
// 实际应用:创建分隔线
function createDivider(char = '-', length = 30) {
return char.repeat(length);
}
console.log(createDivider()); // '------------------------------'
console.log(createDivider('=', 20)); // '===================='
// 实际应用:文本对齐
function padLeft(text, width, char = ' ') {
if (text.length >= width) return text;
return char.repeat(width - text.length) + text;
}
console.log(padLeft('123', 5)); // ' 123'
console.log(padLeft('abc', 6, '*')); // '***abc'
15. padStart() 和 padEnd() - 填充字符串(ES2017)
let str = '5';
// padStart(targetLength, padString) - 在开头填充
console.log(str.padStart(3, '0')); // '005'
console.log(str.padStart(5, 'ab')); // 'abab5'
console.log(str.padStart(2)); // ' 5'(默认用空格)
// padEnd() - 在末尾填充
console.log(str.padEnd(3, '0')); // '500'
console.log(str.padEnd(5, 'ab')); // '5abab'
// 实际应用:格式化序号
function formatNumber(num, digits = 3) {
return num.toString().padStart(digits, '0');
}
for (let i = 1; i <= 10; i++) {
console.log(`编号:${formatNumber(i)}`); // 001, 002, 003...
}
// 实际应用:表格对齐
function printTable(rows) {
rows.forEach(([key, value]) => {
console.log(
key.padEnd(10) + ' | ' +
value.toString().padStart(8)
);
});
}
printTable([
['名称', '价格'],
['苹果', 5],
['香蕉', 3],
['西瓜', 8]
]);
16. match() - 正则匹配
let str = '今天是2026年3月13日,气温15°C';
// 匹配数字
let numbers = str.match(/\d+/g);
console.log(numbers); // ['2026', '3', '13', '15']
// 匹配日期
let dateMatch = str.match(/(\d+)年(\d+)月(\d+)日/);
if (dateMatch) {
console.log('完整匹配:', dateMatch[0]); // '2026年3月13日'
console.log('年:', dateMatch[1]); // '2026'
console.log('月:', dateMatch[2]); // '3'
console.log('日:', dateMatch[3]); // '13'
}
// 实际应用:提取邮箱中的用户名和域名
function parseEmail(email) {
let match = email.match(/^([^@]+)@(.+)$/);
if (!match) return null;
return {
username: match[1],
domain: match[2]
};
}
console.log(parseEmail('zhangsan@example.com'));
// { username: 'zhangsan', domain: 'example.com' }
17. search() - 搜索正则匹配的位置
let str = 'Hello, 123 World! 456';
console.log(str.search(/\d+/)); // 7(第一个数字的位置)
console.log(str.search(/[A-Z]/)); // 0(第一个大写字母)
console.log(str.search(/[a-z]/)); // 1(第一个小写字母)
console.log(str.search(/[x-z]/)); // -1(找不到)
// 实际应用:检查字符串是否包含特定模式
function hasPattern(text, pattern) {
return text.search(pattern) !== -1;
}
console.log(hasPattern('user@example.com', /@/)); // true
console.log(hasPattern('电话号码:13800138000', /\d{11}/)); // true
18. localeCompare() - 本地化比较
let names = ['张三', '李四', '王五', '赵六', '陈七'];
// 默认排序(不符合中文习惯)
console.log([...names].sort());
// 使用localeCompare进行中文排序
let sortedCN = [...names].sort((a, b) => a.localeCompare(b, 'zh-CN'));
console.log(sortedCN); // 按照中文拼音排序
// 忽略大小写比较
let str1 = 'Apple';
let str2 = 'apple';
console.log(str1.localeCompare(str2, undefined, { sensitivity: 'base' })); // 0(视为相等)
// 实际应用:多语言排序
function sortMultilingual(array, locale = 'zh-CN') {
return [...array].sort((a, b) => a.localeCompare(b, locale));
}
let mixed = ['éclair', 'apple', 'zebra', 'café'];
console.log(sortMultilingual(mixed, 'fr')); // 法语排序
课程知识要点
-
字符串定义:字符的,可用单引号、双引号、反引号创建
-
访问字符:charAt()、方括号[]、at()(ES2022)
-
查找方法:indexOf()、lastIndexOf()、includes()、startsWith()、endsWith()
-
提取方法:slice()、substring()、substr()(遗留)
-
转换方法:toLowerCase()、toUpperCase()、split()、join()
-
替换方法:replace()、replaceAll()(ES2021)
-
填充方法:padStart()、padEnd()、repeat()
-
修剪方法:trim()、trimStart()、trimEnd()
-
正则方法:match()、search()、matchAll()(ES2020)
-
比较方法:localeCompare()支持本地化排序
开发实践建议
基于多年JavaScript开发经验,我对字符串方法的使用建议如下:
// 1. 优先使用现在方法
let text = ' Hello World ';
// 现在(简洁)
if (text.includes('Hello')) { ... }
if (text.startsWith('Hello')) { ... }
let cleaned = text.trim();
// 传统(繁琐)
if (text.indexOf('Hello') !== -1) { ... }
if (text.indexOf('Hello') === 0) { ... }
let cleaned = text.replace(/^\s+|\s+$/g, '');
// 2. 模板字符串优于拼接
let name = '张三';
let age = 25;
// 推荐
let info = `姓名:${name},年龄:${age}`;
// 不推荐
let info2 = '姓名:' + name + ',年龄:' + age;
// 3. 链式调用
let result = ' JavaScript is awesome '
.trim()
.toLowerCase()
.replace('awesome', 'great')
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
console.log(result); // 'JavaScript Is Great'
// 4. 处理用户输入时始终trim
function validateInput(input) {
let value = input.trim();
if (!value) {
return '输入不能为空';
}
return value;
}
// 5. 正则表达式与字符串方法结合使用
function extractEmails(text) {
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
return text.match(emailRegex) || [];
}
let sample = '联系我们:support@example.com 或 sales@company.com.cn';
console.log(extractEmails(sample));
// ['support@example.com', 'sales@company.com.cn']
字符串处理是日常开发中最常见的任务之一,掌握这些方法能够让你更高效地处理文本数据。随着ECMAScript的演进,字符串方法越来越丰富,代码也变得越来越简洁易读。