JavaScript字符串常用方法及技巧

前言

JavaScript字符串常用方法以及一些常用的技巧的总结。学习中,有错误欢迎指正:)
绝大多数方法参考自MDN - String
姊妹篇:JavaScript数组常用属性方法与技巧

String

String 全局对象是用来构造字符串的构造函数。

创建字符串的几种方法

通常我们都使用字符串的字面量写法:

1
2
3
'string text'
"string text"
"中文 español English हिन्दी العربية português বাংলা русский 日本語 ਪੰਜਾਬੀ 한국어"

当然我们也可以使用 String 函数来生成字符串或将其他值转换成字符串。

1
2
String(s)
new String(s)

String() 和运算符 new 一起作为构造函数使用时,它返回一个新创建的 String 对象,存放的是字符串 ss 的字符串表示。
当不用 new 运算符调用 String() 时,它只把 s 转换成一个基本类型的字符串,并返回。此时跟使用字符串字面量是一样的。

举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var s0 = 'hello';
var s1 = new String(s0);
var s2 = String(s0);
console.log(s1 === s0); // false
console.log(s1 === s2); // false
console.log(s0 === s2); // true
console.log(typeof s1); // object
console.log(typeof s0); // string
console.log(typeof s2); // string
s1.foo = 'bar';
s2.foo = 'bar';
console.log(s1.foo); // bar
console.log(s2.foo); // undefined

单个字符访问

获取字符串的某一单个字符有两种方法。 第一种是使用 charAt 方法:

1
'cat'.charAt(1); // "a"

另一种方法 (在ECMAScript 5中有所介绍) 是把字符串当作一个类数组对象,其中的每个字符对应一个数值索引:

1
'cat'[1]; // "a"

使用括号访问字符串不可以对其进行删除或添加,因为对应属性并不是可读或可写的。

原始字符串和 String 对象的区别

1
2
3
4
5
var s1 = "2 + 2"; // 创建一个字符串字面量
var s2 = new String("2 + 2"); // 创建一个字符串对象
console.log(eval(s1)); // 返回number 4
console.log(eval(s2)); // 返回一个字符串对象 "2 + 2"
console.log(eval(s2.valueOf())); // 4

eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
valueOf() 函数返回指定对象的原始值。

数组属性

String.prototype

String.prototype 这个属性表示 String 的原型对象。所有的字符串方法都定义在String.prototype身上,和其他的构造函数一样,你可以通过扩展Stringprototype属性上的方法来给所有字符串实例增加方法。
前面一文说了,Array.prototype 本身是一个数组。
那我们就来看一看 String.prototype 又是什么。

我们可以看到它其实是一个字符串对象。

String.prototype属性也有两个属性:

String.prototype.constructor表示 String 的原型对象的构造函数,它的值就是String函数。表明了所有的数组都是由String函数构造出来的。

String.prototype.length因为String.prototype是个字符串,所有它也有length属性,这个值为 0,因为它是个空字符串对象。

string.length

length属性表示一个0到$2^{32} - 1$的整数,返回一个字符串实例的长度。

string.constructor

constructor属性返回对创建此对象的构造函数(String)的引用。

如:

1
2
var a = 'a';
a.constructor == String;//true

常用字符串方法(不全)

下面介绍一些常用的JavaScript字符串方法,一些不常用的或者还未得到主流浏览器支持的方法暂不作介绍。

String.prototype.charAt()

charAt() 方法返回字符串中指定位置的字符。

语法:

1
str.charAt(index)

参数:

index(必需)0 到 字符串长度-1 的一个整数。

返回值:

返回一个字符。字符串中的字符从左向右索引,第一个字符的索引值为 0,最后一个字符(假设该字符位于字符串 stringName 中)的索引值为 stringName.length - 1 。 如果指定的 index 值超出了该范围,则返回一个空字符串。

例如:

1
2
3
4
5
var anyString = "Brave new world";
anyString.charAt(0) // "B"
anyString.charAt(anyString.length - 1) // "d"
anyString.charAt(999) // " "

String.prototype.charCodeAt()

charCodeAt() 方法返回字符串中指定位置的字符在 Unicode 字符集中的编码值。为 065535 之间的整数。

语法:

1
str.charCodeAt(index)

参数:

index(可选)一个大于等于 0,小于字符串长度的整数。如果不是一个数值,则默认为 0。

返回值:

返回一个 065535 之间的整数。如果 index 是负数,或大于等于字符串的长度,则 charCodeAt() 返回 NaN

例如:

1
"ABC".charCodeAt(0) // returns 65

String.fromCharCode()

String.fromCharCode() 静态方法根据指定的 Unicode 编码中的序号值来返回一个字符串。

语法:

1
String.fromCharCode(num1, ..., numN)

参数:

num1, ..., numN(必须)一组序列数字,表示 Unicode 值。

返回值:

该方法返回一个字符串,而不是一个 String 对象。

例如:

1
String.fromCharCode(65,66,67) // "ABC"

String.prototype.concat()

concat() 方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。

语法:

1
str.concat(string2, string3[, ..., stringN])

参数:

string2...stringN 和原字符串连接的多个字符串。

返回值:

该方法返回一个新的字符串,是一个或多个字符串与原字符串连接合并。该方法不影响原字符串。

例如:

1
2
3
// 将多个字符串与原字符串合并为一个新字符串
var hello = "Hello, ";
console.log(hello.concat("Kevin", " have a nice day.")); /* Hello, Kevin have a nice day. */

强烈建议使用赋值操作符(+, +=)代替 concat 方法。性能更好。

String.prototype.indexOf()

indexOf() 方法返回指定值在字符串对象中首次出现的位置。从 fromIndex 位置向后开始查找,如果不存在,则返回 -1

语法:

1
str.indexOf(searchValue[, fromIndex])

参数:

searchValue 一个字符串,表示被查找的值。

fromIndex(可选)表示调用该方法的字符串中开始查找的位置。可以是任意整数。默认值为 0。如果 fromIndex < 0 则查找整个字符串(如同传进了 0)。如果 fromIndex >= str.length,则该方法返回 -1,除非被查找的字符串是一个空字符串,此时返回 str.length。如果被查找的字符串为空字符串且 0 <= fromIndex < str.length 则返回 fromIndex

返回值:

返回一个整数。表示指定值在字符串对象中首次出现的位置。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
"Blue Whale".indexOf("Blue"); // returns 0
"Blue Whale".indexOf("Blute"); // returns -1
"Blue Whale".indexOf("Whale", 5); // returns 5
"Blue Whale".indexOf("", 9); // returns 9
"Blue Whale".indexOf("", 11); // returns 10
// 区分大小写
"Blue Whale".indexOf("blue") // returns -1
// 检测是否存在某字符串
"Blue Whale".indexOf("Blue") !== -1; // true
"Blue Whale".indexOf("Bloe") !== -1; // false
// 使用 indexOf 统计一个字符串中某个字母出现的次数
var str = 'To be, or not to be, that is the question.';
var count = 0;
var pos = str.indexOf('e');
while (pos !== -1) {
count++;
pos = str.indexOf('e', pos + 1);
}
console.log(count); // 4

String.prototype.lastIndexOf()

lastIndexOf() 方法返回指定值在调用该方法的字符串中最后出现的位置,如果没找到则返回 -1。从该字符串的后面向前查找,从 fromIndex 处开始。

语法:

1
str.lastIndexOf(searchValue[, fromIndex])

参数:

searchValue 一个字符串,表示被查找的值。

fromIndex(可选)从调用该方法字符串的此位置处开始向前查找。可以是任意整数。默认值为 str.length 。如果为负值,则被看作 0。如果 fromIndex > str.length,则 fromIndex 被看作 str.length

返回值:

返回一个整数。表示指定值在字符串对象中最后出现的位置。

例如:

1
2
3
4
5
"canal".lastIndexOf("a",2) // 1
"canal".lastIndexOf("a",0) // -1
"canal".lastIndexOf("x") // -1
// 区分大小写
"Blue Whale, Killer Whale".lastIndexOf("blue"); // -1

使用 indexOf 和 lastIndexOf:

1
2
3
4
5
6
var anyString = "Brave new world";
anyString.indexOf("w"); // 8
anyString.lastIndexOf("w"); // 10
anyString.indexOf("new"); // 6
anyString.lastIndexOf("new"); // 6

String.prototype.match()

当字符串匹配到正则表达式(regular expression)时,match() 方法会提取匹配项。

语法:

1
str.match(regexp);

参数:

regexp(必需)一个正则表达式对象。如果传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为正则表达式对象。

返回值:

一个包含匹配结果的数组,如果没有匹配项,则返回 null。
如果正则表达式没有 g 标志。而且返回的数组拥有一个额外的 input 属性,该属性包含原始字符串。另外,还拥有一个 index 属性,该属性表示匹配结果在原字符串中的索引(以0开始)。
如果正则表达式包含 g 标志,则该方法返回一个包含所有匹配结果的数组。如果没有匹配到,则返回 null。

例如:

1
2
3
4
5
6
7
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var arr1 = str.match(/[A-E]/gi);// g 全局匹配,i 忽略大小写
console.log(arr1); // ["A", "B", "C", "D", "E", "a", "b", "c", "d", "e"]
var arr2 = str.match(/[A-E]/i);
console.log(arr2); // ["A"]
console.log(arr2.index); // 0
console.log(arr2.input); // ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

search() 方法执行一个查找,看该字符串对象与一个正则表达式是否匹配。

语法:

1
str.search(regexp)

参数:

regexp(必需)
一个正则表达式对象。如果传入一个非正则表达式对象,则会使用 new RegExp(obj) 隐式地将其转换为正则表达式对象。

返回值:

返回一个整数,该整数是正则表达式在字符串中首次匹配项的索引。否则,返回 -1。

例如:

1
2
3
var str = "321ABC123";
var index = str.search(/ABC/);
console.log(index);

String.prototype.replace()

replace() 方法使用一个替换值(replacement)替换掉一个匹配模式(pattern)在原字符串中某些或所有的匹配项,并返回替换后的新的字符串。
第一个参数—-替换模式(pattern)可以是一个字符串或者一个 RegExp。
第二个参数—-替换值(replacement)可以是一个字符串或者一个函数。
该方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。

语法:

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

参数:

regexp (pattern)
一个 RegExp 对象或者其字面量。如果要替换所有匹配项则该正则表达式需包含 g 标志。

substr (pattern)
一个要被 newSubStr 替换的字符串。此时只有第一个匹配项会被替换。

1
2
3
4
// 当第一个参数为字符串时,只有第一个匹配项会被替换
'I am loser,You are loser'.replace('loser','hero');//I am hero,You are loser
// 使用正则表达式并包含 g 标志时,所有匹配项都会被替换
'I am loser,You are loser'.replace(/loser/g,'hero')//I am hero,You are hero

newSubStr (replacement)
用于替换第一个参数在原字符串中的匹配到的所有匹配项的字符串。该字符串中可以内插一些特殊的变量名。参考下面的表格使用字符串作为参数:

变量名 代表的值
$$ 代表一个 “$” 字符
$& 代表当前匹配的子串
$` 代表当前匹配的子串左边的内容
$’ 代表当前匹配的子串右边的内容
$n 假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么代表第 n 个括号匹配的字符串

可能解释的比较模糊,参见下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// $$ 代表 "$" 字符串
"ABC123abc123def".replace("ABC","{$$}"); // "{$}123abc123def"
"ABC123abc123def".replace(/ABC/gi,"{$$}"); // "{$}123{$}123def"
// $& 代表 当前匹配到的字符串
"ABC123abc123def".replace("ABC","{$&}"); // "{ABC}123abc123def"
"ABC123abc123def".replace(/ABC/gi,"{$&}"); // "{ABC}123{abc}123def"
// $` 代表 当前匹配到的字符串左边的内容
"ABC123abc123def".replace("ABC","{$`}"); // "{}123abc123def"
"ABC123abc123def".replace(/ABC/gi,"{$`}"); // "{}123{ABC123}123def"
// $' 代表 当前匹配到的字符串左边的内容
"ABC123abc123def".replace("ABC","{$'}"); // "{123abc123def}123abc123def"
"ABC123abc123def".replace(/ABC/gi,"{$'}"); // "{123abc123def}123{123def}123def"
// $n 代表 第n个括号匹配的字符串
"ABC123abc123def".replace(/(ABC)(123)/gi,"{$2$1}"); // "{123ABC}{123abc}def"

function (replacement)
一个用来创建新的子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。如果第一个参数是正则表达式,且为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用。
下面是该函数的参数:

变量名 代表的值
match 匹配的子串。(对应于上述的$&。)
p1,p2, … 假如replace()方法的第一个参数是一个RegExp 对象,则代表第n个括号匹配的字符串。(对应于上述的$1,$2等。)
offset 匹配到的子字符串的首字符的索引。
string 被匹配的原字符串。

精确的参数个数依赖于replace()的第一个参数是否是一个正则表达式对象, 以及这个正则表达式中指定了多少个括号子串。

参考下面的指定一个函数作为参数:

1
2
3
4
5
6
7
8
9
function repFun() {
console.log(arguments);
return '返回值';
}
'ABC123ABC123abcdef'.replace(/(ABC)(123)/g, repFun)
// ["ABC123", "ABC", "123", 0, "ABC123ABC123abcdef"]
// ["ABC123", "ABC", "123", 6, "ABC123ABC123abcdef"]
// "返回值返回值abcdef"
// 可以看到函数的arguments有n+3(n为正则括号匹配的次数)个。

返回值:

返回一个匹配替换之后的新字符串。

例如:

交换字符串中的两个单词:

1
2
3
4
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr); // Smith, John

使用行内函数来修改匹配到的字符:

1
2
3
4
5
6
7
function styleHyphenFormat(propertyName) {
function upperToHyphenLower(match) {
return '-' + match.toLowerCase();
}
return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
}
styleHyphenFormat("borderTop") // "border-top"

String.prototype.slice()

slice() 方法提取字符串中的一部分,并返回这个新的字符串。
该方法不会修改原字符串。

语法:

1
str.slice(beginSlice[, endSlice])

参数:

beginSlice(必需)从该索引(以 0 为基数)处开始提取原字符串中的字符。如果值为负数,会被当做 str.length + beginSlice 看待。

endSlice(可选)在该索引(以 0 为基数)处结束提取字符串(但不包含该字符)。如果省略该参数,slice会一直提取到字符串末尾。如果该参数为负数,则被看作是 str.length + endSlice。

返回值:

返回一个新的字符串,该字符串是由slice()方法提取原字符串的一部分。

例如:

1
2
3
4
5
var str1 = 'The morning is upon us.';
var str2 = str1.slice(4, -2);
console.log(str1); // "The morning is upon us." 原字符串并没有改变
console.log(str2); // "upon u"

String.prototype.substr()

substr() 方法返回字符串中从指定位置开始到指定长度的子字符串。
该方法不会改变原字符串。

语法:

1
str.substr(start[, length])

参数:

start(必需)开始提取字符的位置。如果 start 为正值,且大于或等于字符串的长度,则 substr 返回一个空字符串。如果为负值,则被看作 str.length + start。 如果 Math.abs(start) 大于字符串的长度,则 substr 使用 0 作为开始提取的索引。

length(可选)提取的字符数。

返回值:

返回一个新的字符串

例如:

1
2
3
4
5
6
var str = "abcdefghij";
str.substr(1,2) //"bc"
str.substr(-3) //"hij"
str.substr(-20,2) //"ab"
str.substr(20,2) //""

String.prototype.substring()

substring() 返回字符串两个索引之间(或到字符串末尾)的子串。
该方法不会改变原字符串。
该方法跟slice()方法很相似,但是不够slice()方法灵活,因为其参数索引不能超过原字符串的长度范围。

语法:

1
str.substring(indexStart[, indexEnd])

参数:

indexStart(必需)一个 0 到字符串长度之间的整数。

indexEnd(可选)一个 0 到字符串长度之间的整数。

substring 提取从 indexStart 到 indexEnd(不包括)之间的字符。特别地:

  • 如果 indexStart 等于 indexEnd,substring 返回一个空字符串。
  • 如果省略 indexEnd,substring 提取字符一直到字符串末尾。
  • 如果任一参数小于 0 或为 NaN,则被当作 0。
  • 如果任一参数大于 stringName.length,则被当作 stringName.length。

如果 indexStart 大于 indexEnd,则从indexEnd提取到indexStart。例如,str.substring(1, 0) == str.substring(0, 1)。

返回值:

返回一个新的字符串

例如:

1
2
3
4
5
6
7
8
9
10
var anyString = "Mozilla";
// 输出 "Moz"
console.log(anyString.substring(0,3));
console.log(anyString.substring(3,0));
console.log(anyString.substring(3,-3));
console.log(anyString.substring(3,NaN));
// 输出 ""
console.log(anyString.substring(4,4));

String.prototype.split()

split() 方法通过把字符串分割成子字符串来把一个 String 对象分割成一个字符串数组
该方法不会改变原字符串。

语法:

1
str.split([separator][, limit])

参数:

separator(可选)指定用来分割字符串的字符(串)。separator 可以是一个字符串或正则表达式。 如果忽略 separator,则返回整个字符串的数组形式。如果 separator 是一个空字符串,则 str 将会把原字符串中每个字符的数组形式返回。

limit(可选)一个整数,限定返回的分割片段数量。返回的数组只会截取最多 limit 个元素。

返回值:

返回一个新的数组。

当字符串为空时,split 返回一个包含一个空字符串的数组,而不是一个空数组。

例如:

1
2
3
4
5
6
7
8
9
var str="How are you doing today?"
str.split(" ") // ["How", "are", "you", "doing", "today?"]
str.split("") // ["H", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", " ", "t", "o", "d", "a", "y", "?"]
str.split(" ",3) // ["How", "are", "you"]
// 如果 separator 包含捕获括号(capturing parentheses),则其匹配结果将会包含在返回的数组中。
var myString = "Hello 1 word. Sentence number 2.";
myString.split(/(\d)/); // ["Hello ", "1", " word. Sentence number ", "2", "."]

String.prototype.toLowerCase()

toLowerCase() 会将调用该方法的字符串值转为小写形式,并返回。
该方法不会改变原字符串。

语法:

1
str.toLowerCase()

参数:

无。

返回值:

返回一个新的字符串。

例如:

1
"ALPHABET".toLowerCase(); // "alphabet"

String.prototype.toUpperCase()

toUpperCase() 会将调用该方法的字符串值转为大写形式,并返回。
该方法不会改变原字符串。

语法:

1
str.toUpperCase()

参数:

无。

返回值:

返回一个新的字符串。

例如:

1
"ALPHABETalphabet".toUpperCase(); // "ALPHABET"

String.prototype.trim()

trim() 方法会删除一个字符串两端的空白字符。
该方法不会改变原数组。

语法:

1
str.trim()

参数:

无。

返回值:

返回一个新的字符串。

例如:

1
2
var orig = ' foo ';
orig.trim(); // 'foo'

浏览器兼容:IE9+

兼容性处理:

1
2
3
4
5
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
};
}

String.prototype.toString()

String.prototype.valueOf()

###

参考来源

String - MDN
JavaScript String 对象 - W3C