js 字符串常用方法

String对象是JavaScript原生提供的三个包装对象之一,用来生成字符串对象。对字符串操作不够重视,没有特别去了解下字符串的操作,最近在写一些小脚本的时候常用到字符串操作,所以特地来整理下。

String.charAt() 指定位置的字符

charAt方法返回指定位置的字符,字符在字符串中的编号从零开始的位置计数。例如:

1
2
let str = 'teststring';
console.log(str.charAt(3)); // 输出:t

该方法也可以使用数组下标替代:

1
console.log(str[1]); // 输出:e

如果参数为负数或大于等于字符串的长度,那么该方法返回空字符串。

String.concat() 拼接字符串

concat方法用于将一个或多个字符串与源字符串连接合并,返回一个新字符串,不改变源字符串。例如:

1
2
3
let str1 = 'hello-', str2 = 'world-', str3 = 'thanks-';
const newStr = str1.concat(str2, str3, str1);
console.log(newStr); // 输出:hello-world-thanks-hello-

出于性能考虑,建议使用赋值操作符(+、+=)代替concat方法。

String.slice() 提取子串

slice方法用于从源字符串中取出子字符串并返回,不改变源字符串。

语法:string.slice(beginIndex[, endIndex])。从beginIndex索引处开始提取源字符串中的字符,直到endIndex索引处(可选)结束提取。注意:

  • 如果beginIndex为负值,会被当做sourceLength + beginSlice看待,也就是从末位倒数。例如:

    1
    2
    3
    let str = 'abcdefghigklmnopqrstuvwxyz';
    console.log(str.slice(-3)); // 输出 xyz
    // 这里beginIndex = str.length + (-3) = 26 - 3 = 23; 从倒数第三个开始提取字符串,得出xyz。
  • endIndex省略,则会从beginIndex开始一直提取到源字符串末尾。

  • 如果endIndex为负数,则被看做是sourceLength + endLength。
    1
    console.log(str.slice(-6, -3)); // 输出:uvw

注意:slice()方法提取新字符串从beginIndex开始,到endIndex结束,但是不包括endIndex的字符。例如:

1
console.log(str.slice(1, 2)); // 输出:b

beginxIndex=1的字符为b,endIndex=2处的字符为c,但是返回的新字符串为b,不是bc

String.substring() 提取子串

substringslice相似,不同的是参数的处理方式,先看语法: str.substring(indexStart[, indexEnd])。即提取从索引位置1到索引位置2处(不包括)截止的字符串。

substring处理的特殊情况:

  • 如果任一参数小于0或为NAN,则被当做0来处理。
  • 如果任一参数大于源字符串长度,则被当做源字符串长度处理。
  • 如果indexStart大于indexEnd,则执行的结果等效于两个参数调换的结果。
  • 如果indexStart等于indexEnd,则返回空。

String.substr() 提取字符串

substr方法用于从源字符串中提取子串,和slicesubstring方法相同。看看语法:str.substr(start[, length])substr的第二个参数是偏移量,但是substring第二个参数是源字符串的索引,即从索引start处开始,截取长度为length的字符串。如果start为负值,则被看做是源字符串的长度+start。

substr处理的特殊情况:

  • 如果start为正值,且大于或等于字符串的长度,则返回一个空字符串
  • 如果start为负值,则处理为从字符串末尾开始的一个索引(如果start为负值,且绝对值大于字符串的长度,则处理为0.
  • 如果length为0或负值,则返回一个空字符串
  • 如果忽略length,则提取到字符串的末尾。
1
2
const str = 'abcdefghijklomn';
console.log(str.substr(-3)); // 输出:omn

String.indexOf() 查找字符串第一次出现的位置

indexOf方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。如果返回-1,表示没找到:

1
2
const str = 'abcdefghijklomn';
console.log(str.indexOf('def')); // 输出:3

indexOf方法还可以接受第二个参数,表示从该位置开始向后匹配:

1
2
3
const str = 'abcdefghijklomn';
console.log(str.indexOf('def', 2)); // 输出3
console.log(str.indexOf('def', 4)); // 输出-1,没找到

第二个参数只是指定从某个位置,开始向后匹配,但里面字符的位置索引还是一样的。

lastIndexOf()方法和indexOf()方法的功能一样,但是区别是lastIndexOf从尾部开始匹配,indexOf则是从头部开始匹配;而且lastIndexOf()的第二个参数表示从该位置起向前匹配:

1
2
3
4
const str = '01234567890123456789';
console.log(str.lastIndexOf('9')); // 输出19
console.log(str.lastIndexOf('9', 10)); // 输出9
console.log(str.lastIndexOf('9', 1)); // 输出-1

String.trim() 去除字符串两侧的空白字符

trim()方法用来删除字符串两侧的空白字符,空白字符包括:空格、制表符(\t \v)、换行符(\n)、回车符(\r)。该方法生成新的字符串,源字符串不受改变。

1
2
const str = '   01234567890123456789  \n';
console.log(str.trim()); // 输出:01234567890123456789

String.toLowerCase() 转换为小写 String.toUpperCase() 转化为大写

toLowerCase()方法将字符串的字母全部转换为小写。toUpperCase()方法将字符串的字符全部转换为大写。他们都创建新的字符串,不改变原有字符串。

1
2
3
const str = 'To, or not to be. 2014'
console.log(str.toUpperCase()); // TO, OR NOT TO BE. 2014
console.log(str.toLowerCase()); // to, or not to be. 2014

String.split() 分割字符串

split方法按照给定的规则分割字符串,返回一个由分割字符串分割出来的子字符串组成的数组。该方法还可以接受第二个参数,限定返回数组的最大成员数,例如:

1
2
3
const str = '|test|base|coin|def|'
console.log(str.split('|')); // 输出:[ '', 'test', 'base', 'coin', 'def', '' ]
console.log(str.split('|', 3)); // 输出:[ '', 'test', 'base' ]

需要注意的点:

  • 如果分割字符串为空字符串,则返回的数组成员是源字符串的每一个字符串
  • 如果省略分割字符串,则返回的数组只有一个源字符串
  • 如果满足分割规则的两个部分相邻(分割字符串中间没有其他字符串),则返回数组之中会有一个空字符串
  • 如果满足分割规则的部分位于字符串的开头或结尾,则返回数组的第一个或最后一个成员是一个空字符串

split方法的分割字符串也可以为正则表达式,如果分割符为包含括号的正则表达式,则每次分割符匹配时,捕获括号的结果(包括任何未定义的结果)将被拼接到输出数组中(但是并不是所有浏览器都支持此功能)。例如:

1
2
const str = '1.test;2.local;3.admin';
console.log(str.split(/(\d)/)); // 输出:[ '', '1', '.test;', '2', '.local;', '3', '.admin' ]

String.match() 匹配子字符串

match方法用于确定源字符串是否匹配某个子字符串,返回一个数组。如果没有匹配,则返回null:

1
2
3
const str = '1.test;2.local;3.admin';
console.log(str.match('test')); // 输出:[ 'test', index: 2, input: '1.test;2.local;3.admin' ]
console.log(str.match('test1')); // 输出:null

可以看到,如果匹配成功的话,返回的数组还有index属性和input属性,分别表示匹配字符串开始的位置和原始字符串。

注意,match方法的参数需要的事一个正则表达式对象,如果传入的是一个非正则表达式对象,则会隐式调用new RegExp(obj)对象来将其转换为一个RegExp。例如:

1
2
3
4
5
const str = 'NaN number 33 null';
console.log(str.match(NaN)); // 输出:[ 'NaN', index: 0, input: 'NaN number 33 null' ]
console.log(str.match(+33)); // 输出:[ '33', index: 11, input: 'NaN number 33 null' ]
console.log(str.match(-33)); // 输出:null
console.log(str.match(null)); // 输出:[ 'null', index: 14, input: 'NaN number 33 null' ]

如果正则表达式包含g标志,则该方法返回一个数组,它包含所有匹配的子字符串而不是匹配对象。捕获租不会被返回(不会返回index和input),如果没匹配到,则返回null;

1
2
const str = 'NaN number 33 null 44 55';
console.log(str.match(/(\d\d)/g)); // 输出:[ '33', '44', '55' ]

String.prototype.replace() 替换

replace()方法返回一个由替换值替换一些或所有匹配的模式后的新字符串。模式可以是一个字符串,也可以是一个正则表达式。替换值可以是一个字符串或者一个每次匹配都要调用的函数。注意:源字符串不会改变。在进行全局的搜索替换时,正则表达式需要包含g标志。

语法:

1
str.replace(regexp | substr, newSubStr | function)

使用字符串作为参数

替换字符串可以插入下面的特殊变量名:
| 变量名 | 代表的值 |
| —— | —— |
| $$ | 插入一个$ |
| $& | 插入匹配的子串 |
| $ | 插入当前匹配的子串左边的内容 |
| $' | 插入当前匹配的子串右边的内容 |
| $n | 如果第一个参数是正则匹配,那么插入第n个括号匹配的字符串。|

1
2
3
4
const str = 'left-33-right';
console.log(str.replace('33', "$&")); // 输出:left-33-right
console.log(str.replace('33', "$`")); // 输出:left-left--right
console.log(str.replace('33', "$'")); // 输出:left--right-right

指定一个函数为参数

可以指定一个函数作为第二个参数,当匹配执行后,该函数就会执行,函数的返回值作为替换字符串。如果第一个参数为正则表达式,那么这个方法将会调用多次。函数的参数为:
| 变量名 | 代表的值 |
| —— | —— |
| match | 匹配的字符串(对应上面变量的$&)|
| p1,p2,p3…. | 如果第一个参数是正则表达式,那么pn代表第n个括号匹配的字符串。例如,正则表达式为/(\a+)(\b+)/,那么对应的p1就是匹配\a+,p2就是匹配的\b+。|
| offset | 匹配到的子字符串在源字符串中的偏移量 |
| string | 被匹配的源字符串 |

1
2
3
4
5
const str = 'abc12345#$*%';
console.log(str.replace(/([^\d]*)(\d*)([^\w]*)/, function(match, p1, p2, p3, offset, string) {
return [p1, p2, p3].join(' - ');
}));
// 输出:abc - 12345 - #$*%


对常用的字符串操作的一个整理。
参考文章:
String 对象
MDN String

码字辛苦,打赏个咖啡☕️可好?💘