前言
在js中,String
类型是我们在处理数据时最常接触的类型之一了。但是String
类型已经存在惊人的51个方法了,不知道你是用过几种。
String
类型也是最万能的,在js中任何类型都可以转成字符串类型,但反过来就不一定了,所以这好像理解了为什么平平无奇的String
类型可以有这么多方法了。
这么多方法当然也存在一些不被推荐的方法,准备删除或出于兼容性而保留的,但是部分浏览器也还支持。以下会单独分开说,可以作为了解。
正文
正常推荐的String方法(37个)
includes 查找一组字符串中是否存在某个字符
此方法用来查找一组字符串中是否存在某个字符,区分大小写。接收两个参数,第一个为希望查找的字符,并且不能是正则表达式,所有传入的参数都将自动转为字符串。第二个参数为要从哪个位置开始查找(可选),默认为0,返回一个布尔值。
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//字符中存在,为true
console.log(zhIntroduce.includes("iceCode"));//true
//这里区分大小写,因为这组字符串中没有大写I开头的这个单词,所以为false
console.log(zhIntroduce.includes("IceCode"));//false
//所传的参数会默认转成字符串,所以这里查找的就是'undefined',这组字符串并没有,所以为false
console.log(zhIntroduce.includes(undefined));//false
indexOf 查找一组字符串中的某个字符,并返回索引
这个方法同includes
差不多,同样会查找一组字符串中是否存在某个字符,不同的是indexOf
是返回一个索引,而includes
返回的是一个布尔值。接收两个参数,第一个为希望查找的字符,规则同includes
,第二个为想要从哪个地方查找(可选),返回查找字符第一次出现的索引,没找到则返回-1。
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
console.log(zhIntroduce.indexOf("iceCode"));//2
//第一次查找到字符的索引
console.log(zhIntroduce.indexOf("多"));//17
//区分大小写,没找到所以未-1
console.log(zhIntroduce.indexOf("IceCode"));//-1
//空字符串会返回想要查找的索引位置,默认为0,所以当没有传第二个参数时就是0,传X就是X
console.log(zhIntroduce.indexOf(""));//0
console.log(zhIntroduce.indexOf("", 18));//18
lastIndexOf indexOf的反向查找版
lastIndexOf
与indexOf
的区别就是,lastIndexOf
是从后往前找,并且查找到这组字符串中唯一值的结果不会改变(当查找空字符串时,返回的结果可能会有一丝变化),接收参数与indexOf
相同。返回查找字符串最后一次出现的索引,没找到为-1
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
console.log(zhIntroduce.lastIndexOf("iceCode"));//2
//最后一次查找到字符的索引
console.log(zhIntroduce.lastIndexOf("多"));//18
//没找到就是-1
console.log(zhIntroduce.lastIndexOf("IceCode"));//-1
//这里得空字符串得到的结果为这组字符串的长度,而不是0,当存在第二个参数时结果为第二个参数
console.log(zhIntroduce.lastIndexOf(""));//22
console.log(zhIntroduce.lastIndexOf("", 18));//18
padStart 从前往后重复填充字符到指定长度
此方法会重复填充给定的字符到指定长度,接收两个参数,第一个为指定长度,第二个是要填充的字符,返回一个最终指定长度并包含重复填充字符的字符串,如果第一个指定的长度小于当前字符的长度则返回原字符串
//看上面文字描述可能有点不太好理解,直接看代码就非常好理解了
//当前定义的字符串长度为7
const name = "iceCode";
//这里指定了长度为20,然后填充指定字符'e'最后返回的是一个长度为20的字符串,从前往后填充
console.log(name.padStart(20, "e"));//eeeeeeeeeeeeeiceCode
//当填充长度小于当前字符串长度,则返回当前字符串
console.log(name.padStart(5, "666"));//iceCode
padEnd 从后往前重复填充字符到指定长度
这个方法同padStart
几乎类似,差别就是这个方法是从后往前填充。接收参数同padStart
相同,返回值的规则与padStart
相同
const name = "iceCode";
//返回一个长度为20的字符串,要填充的字符是从后往前填充
console.log(name.padEnd(20, "e"));//iceCodeeeeeeeeeeeeee
//指定长度没有当前字符长,同样会返回当前字符串
console.log(name.padEnd(5, "666"));//iceCode
replace 替换指定字符
replace
只会替换第一个找到匹配字符的元素然后进行替换,接收两个参数,第一个为要被替换的字符(任何不是String
类型的参数,都会被转成String
处理),可以是正则表达式,第二个为替换为的字符,返回被替换后一个新的字符串。
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//每个字符前都会有空字符,所以替换第一个找到的空字符就是再最前面
console.log(zhIntroduce.replace("", "_")); //_我是iceCode,初来乍到,还请多多关照。
//这里只会替换第一个标点符号
console.log(zhIntroduce.replace(",", ":"));//我是iceCode:初来乍到,还请多多关照。
//正则也是可以的,将多这个字替换为少,也是只替换找到的第一个
console.log(zhIntroduce.replace(/多/, "少"));//我是iceCode,初来乍到,还请少多关照。
//正则可以多个匹配,加个g,这样就可以全局替换了
console.log(zhIntroduce.replace(/多/g, "少"));//我是iceCode,初来乍到,还请少少关照。
//也可以使用正则全局不区分大小写匹配
console.log(zhIntroduce.replace(/c/gi, "D"));//我是iDeDode,初来乍到,还请多多关照。
另外替换为的字符也可以是特殊替换模式,不过需要使用正则表达式进行查找
- 使用
$&
插入匹配的子字符串:
const name = "iceCode";
//这里$&就是匹配到的字符,并拼接上新的字符替换掉它,最后的结果就是Hi,iceCode
//是这样替换的 ice->Hi,ice
console.log(name.replace(/ice/g, "Hi,$&"));//Hi,iceCode
- 使用
$$
插入字符串$:
const name = "iceCode";
//这里很好理解 两个$和一个$效果是一样的
console.log(name.replace(/ice/g, "$$"));//$Code
- 使用
$`
(反引号)插入匹配子字符串之前的字符串片段:
const name = "iceCode";
//使用$`代表了匹配到的字符之前所有的字符 这里代表了iceCo 所以是将de的位置替换为了iceCo
console.log(name.replace(/de/g, "$`"));//iceCoiceCo
- 使用
$'
(单引号)插入匹配子字符串之后的字符串片段:
const name = "iceCode";
//使用$'代表了匹配到的字符之后所有的字符 这里代表了Code 所以是将ice的位置替换为了Code
console.log(name.replace(/ice/g, "$'"));//CodeCode
- 使用
$n
插入第 n 个捕获组:
const name = "iceCode";
//使用$n代表了匹配到的组,n是几就代表了第几组 这里代表了ice 将所匹配到的字符替换为ice
console.log(name.replace(/(ice)Code/g, "$1"));//ice
//这里将匹配到的分为了两组,并将它们反转过来了
console.log(name.replace(/(ice)(Code)/g, "$2$1"));//Codeice
- 使用
$Name
插入名称为 Name 的命名捕获组:
这个例子与上面的例子类似,只是使用了命名捕获组。以下是相应的代码:
const name = "iceCode";
//正则表达式中?<变量>... 这里?后的变量名为命名捕获组的名,可以在替换中使用,...代表了命名捕获组存的数据
//使用的时候$<变量> 就可以了
//这里匹配到了iceCode $<im>就是ice 拼接d,CODE 最后的结果就是iced,CODE
console.log(name.replace(/(?<im>ice)(Code)/g, "$<im>d,CODE"));//iced,CODE
这里对正则表达式的掌握还是有一些的,如果想要了解正则表达式比较多后面会出一篇关于正则的文章
另外,替换为的参数也可以是一个回调函数,传入一个参数,是匹配到的元素,这个回调函数可以作为一个简单工厂函数来操作
const name = "iceCode";
//这里将匹配到的字符转成大写在返回出来替换原来字符
console.log(name.replace("ice", (v) => v.toUpperCase()));//ICECode
replaceAll 替换一段字符串中全部指定字符
replaceAll兼容性有些不太好,需要node15以上,老项目中谨慎使用
此方法相当于replace
的补全版,因为replace
在不使用正则的情况下,只能匹配到一段字符串中第一个找到的字符,对于要替换所查找到的所有指定字符时可能会有些麻烦,使用replaceAll
可以方便的替换所有指定字符。参数和指定被替换的字符与repalce
相同,这里就不多写了
const introduce = "I'm iceCode.I am inexperienced, but also invite more attention.";
//这里加了空格 所以匹配到的都会多出空格
console.log(introduce.replaceAll("e", " E "));//I'm ic E Cod E .I am in E xp E ri E nc E d, but also invit E mor E att E ntion.
slice 截取字符串
slice
截取对应索引的字符串,并返回一个新的字符串,不会改变原数组。接收两个参数,第一个为开始截取的索引位置,第二个为截取结束位置的索引(可选),不包括第二个参数索引位置的元素,返回一个新的截取后的字符串。
const name = "iceCode";
//只传一个参数,会从传入的索引位置截取到最后
console.log(name.slice(1));//ceCode
//不包含第二个索引位置的字符
console.log(name.slice(1, 5));//ceCo
//可以为负数,如果第一个小于第二个参数则会返回空
console.log(name.slice(-5, -1));//eCod
substring 截取字符串
substring
与slice
效果相同,区别在于他们传的参数,不同参数会有不同区别。同样接受两个参数,参数同样的效果,同样不改变原数组,同样返回要给新的截取后的字符串
//效果都知道,这里只说它们的却别
const name = "iceCode";
//substring的参数不能为负数,否者会返回空,slice可以,只要第一个参数小于第二个参数即可
console.log(name.substring(-3, -1));//''
console.log(name.slice(-3, -1));//od
//substring的正数参数的时候可以第一个参数大于第二个参数,与两个数反过来填的结果是一样的
//slice不可以,如果是则返回空
console.log(name.substring(3, 1));//ce
console.log(name.slice(3, 1));//''
split 指定字符分割成数组
split
可以将字符串以指定元素分割成一个数组,可以说是String
方法中比较常用的一个了,接收两个参数,第一个为指定字符,对字符串进行分割为数组,第二个为分割的数组最大长度,返回一个数组。
const name = "iceCode";
//如果不传参数,则会将整个字符串放到数组中
console.log(name.split());//[ 'iceCode' ]
//如果找不到或不是字符一样会将整个字符串放到数组中
console.log(name.split(1));//[ 'iceCode' ]
console.log(name.split("f"));//[ 'iceCode' ]
//分割的字符在最后一位分割,数组中会多一个空字符串
console.log(name.split("e"));//[ 'ic', 'Cod', '' ]
//当为空字符串时,字符串中的每一个字符都将作为一个元素放到数组中
console.log(name.split(""));//["i", "c", "e", "C", "o", "d", "e"];
//这里可以传入第二个参数限制整个返回的数组的长度,避免过长
console.log(name.split("", 2));//["i", "c"];
//这里参数也可以是一个正则表达式,正常情况下是区分大小写的这个使用正则让它不区分大小写
console.log(name.split(/c/i));//[ 'i', 'e', 'ode' ]
toUpperCase 将英文字符串转换成大写
toUpperCase
作用很简单,就是将英文字符串转换成大写英文,如果是汉字则返回原字符串
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里可以发现只是将英文转换了,汉字是不会改变的
console.log(zhIntroduce.toUpperCase());//我是ICECODE,初来乍到,还请多多关照。
toLowerCase 将英文字符串转换成小写字符串
toLowerCase
作用一样很简单,就是将英文字符串转换成小写英文,如果是汉字则返回原字符串
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里可以发现只是将英文转换了,汉字是不会改变的
console.log(zhIntroduce.toLowerCase());//我是icecode,初来乍到,还请多多关照。
toLocaleUpperCase 根据特定时区将字符串转化成大写
toLocaleUpperCase
根据特定区域设置的大小写映射规则,将字符串转换为大写形式,接收一个可选的参数,参数规则参考Intl
主页上的参数描述。大多情况下与toUpperCase
一致,只有个别地区的大小写会有些区别。
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//只有少数语言会有细微差距
console.log(zhIntroduce.toLocaleUpperCase('en-US'));//我是ICECODE,初来乍到,还请多多关照。
console.log("Gesäß".toLocaleUpperCase());GESÄSS
toLocaleLowerCase 根据特定时区将字符串转化成小写
toLocaleLowerCase
根据特定区域设置的大小写映射规则,将字符串转换为小写形式,接收一个可选参数,参数规则参考Intl
主页上的参数描述。大多情况下与toLowerCase
一致,只有个别地区的大小写会有些区别。
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//只有少数语言会有细微差距
console.log(zhIntroduce.toLocaleLowerCase('en-US'));//我是icecode,初来乍到,还请多多关照。
console.log("Gesäß".toLocaleLowerCase());gesäß
trim 去除两端空白字符
trim
就非常很好理解,就是去除两端的空格的,一般在表单输入的时候,有可能会有多输入空白字符,可以使用trim
对两端空白字符进行剔除
const name = " iceCode ";
//将两端的空白字符剔除
console.log(name.trim());//iceCode
trimStart、trimEnd 剔除开头空白字符和剔除结尾空白字符
trim
是一次性剔除两端空白字符,显得没有那么灵活。这里trimStart、trimEnd
分别是剔除开头空白字符和剔除结尾空白字符,可以在使用的时候更加灵活。另外trimLeft、trimRight是trimStart、trimEnd的别名
const name = " iceCode ";
//使用别名和它们是相同的效果
console.log(name.trimStart());//'iceCode '
console.log(name.trimLeft());//'iceCode '
console.log(name.trimEnd());//' iceCode'
console.log(name.trimRight());//' iceCode'
concat 拼接字符串
concat
可以对多个字符串相互拼接,接收n个任意类型参数,参数为要拼接的字符串或其他类型参数。这个方法就好比是游泳比赛的救生员一样。因为字符串与任何类型数相加最后都是字符串,这个方法几乎用不到。
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
const name = "iceCode";
//对多个参数进行字符拼接,结果与 字符串+<任意类型数据>是一样的
console.log(zhIntroduce.concat(name, 2, ["666"]));//我是iceCode,初来乍到,还请多多关照。iceCode2666
startsWith 判断一个字符串是否以指定字符串开头
startsWith
接收两个参数,第一个为要查找结尾的字符,可以是任意类型(正则除外),但都会默认转换成字符串,第二个参数为开始的索引,返回个布尔值
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里开头是‘我是icecode’ 所以为true
console.log(zhIntroduce.startsWith("我是iceCode"));//true
//这里传入第二个参数,从索引9的位置开始找,所以,也是对的
console.log(zhIntroduce.startsWith(",", 9));//true
//这里,是英文状态的,所以为false
console.log(zhIntroduce.startsWith(",", 9));//false
endsWith 判断一个字符串是否以指定字符串结尾
endsWith
接收两个参数,第一个为要查找结尾的字符,可以是任意类型(正则除外),但都会默认转换成字符串,第二个参数为结尾的索引(最后一个字符的索引加 1),返回个布尔值
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里结尾的是。 所以为true
console.log(zhIntroduce.endsWith("。"));//true
//这里传入第二个参数,到索引为10的位置就结束,所以,也是对的
console.log(zhIntroduce.endsWith(",", 10));//true
//这里,是英文状态的,所以为false
console.log(zhIntroduce.endsWith(",", 10));//false
charAt 返回给定的索引的字符
charAt
返回一个由给定索引处的单个 UTF-16
码元构成的新字符串。接收一个参数,为要找元素的索引值。返回要找的元素。
const name = "iceCode";
const str = "𠮷𠮾";
//正常情况下会返回由UTF-16码元构成的字符,当如果索引值大于当前字符串的长度或小于0的时候会返回空
console.log(name.charAt(2));//e
console.log(name.charAt(8));//''
//这里生僻字返回的是孤项代理,不是有效的Unicode 字符,所以无法显示
console.log(str.charAt(0));//�
charCodeAt 给定索引处的 UTF-16 码元
此方法与charAt
相似,只是返回值不同,charAt
返回的是由UTF-16
码元构成的新字符串,而charCodeAt
返回的则直接是一个码元,其值介于 0
和 65535
之间。
const name = "iceCode";
const str = "𠮷𠮾";
//返回索引位置字符的UTF-16 码元
console.log(name.charCodeAt(2));//101
//如果索引超过当前元素的长度,则返回NAN
console.log(name.charCodeAt(8));//NAN
//这里生僻字的码元为55362 但不是有效的Unicode 字符
console.log(str.charCodeAt(0));//55362
normalize 返回字符串 Unicode 标准化形式
了解Unicode可以查看:Unicode字符表 (rapidtables.org)
normalize
返回一个Unicode
标准化形式,接收一个可选参数,参数值为:
- NFC:规范分解,然后进行规范组合。
- NFD:规范分解。
- NFKC:兼容分解,然后进行规范组合。
- NFKD:兼容分解。
如果normalize
没有传入参数(undefined
),则按照NFC来解析。正常来说一个Unicode
编码在使用normalize
(不传参)和不使用normalize
的时候得到的结果大致是一样的。
//这里随便找了几个Unicode编码
const name1 = "\u2fd2\u2fd3\u2fd5\u01C4";
//可以看出在没有传参的时候,得到的结果是一致的
console.log(name1);//⿒⿓⿕DŽ
console.log(name1.normalize());//⿒⿓⿕DŽ
//当使用了一些参数后,可以看出结果会有少许改变,组合字DŽ也被分解了
console.log(name1.normalize());//⿒⿓⿕DŽ
console.log(name1.normalize("NFKC"));//齒龍龠DŽ
codePointAt 给定索引开始的字符的 Unicode 码位值
该整数是从给定索引开始的字符的 Unicode
码位值。请注意,索引仍然基于 UTF-16
码元,而不是 Unicode
码位。有关 Unicode
的信息,请参阅 UTF-16 字符、Unicode 码位和字素簇。
const name = "iceCode";
const str = "𠮷𠮾";
//这里可以看出返回的Unicode 码位值和UTF-16 码元是一样的
console.log(name.codePointAt(2));//101
//如果索引超过当前元素的长度,这里会返回undefined
console.log(name.codePointAt(8));//undefined
//这里可以看出返回的Unicode 码位值是有的,但是和Unicode 字符不一样
console.log(str.codePointAt(0));//134071
//特殊字符的Unicode 码位值
console.log("😍".codePointAt(0));//128525
at 查找索引位置的字符
此方法兼容性一般,node版本需要16.6.0以上,生产环境谨慎使用
字符串的at
方法与数组的at
方法类似,返回结果如果有与charAt
一致,接收一个参数,为一个整数,可以是正整数也可以为负数,返回指定位置的单个 UTF-16
码元组成的字符,负数的时候从后往前找。
const name = "iceCode";
const str = "𠮷𠮾";
//正数的时候与charAt一致
console.log(name.at(2));//e
//负数的时候,从后往前找
console.log(name.at(-2));//d
//没找到就是undefined
console.log(name.at(8));//undefined
//与charAt的结果一致,此字符不是有效的Unicode 字符
console.log(str.at(-1));//�
match 检索与正则表达式匹配的结果
match
方法会检索与正则表达式匹配的结果,接收一个正则表达式的参数,返回一个数组,如果正则表达式中没有使用g(全局)检索,数组中则会返回检索到元素的详细信息,如果添加了g,则会返回一个包含所有匹配到元素的数组
const name = "iceCode";
//正则表达式包含a-z的所有小写字母,但没有添加g 所以返回第一个匹配到的详细信息数组
console.log(name.match(/[a-z]/));//[ 'i', index: 0, input: 'iceCode', groups: undefined ]
//这里使用了g(全局匹配),返回了所有匹配元素的数组
console.log(name.match(/[a-z]/g));//[ 'i', 'c', 'e', 'o', 'd', 'e' ]
matchAll 返回检索与正则表达式匹配结果的一个迭代器对象
此方法与match
方法很像,但是返回值却大不相同,match
方法返回的是一个正常的数组,matchAll
则是一个迭代器对象(想必对迭代器对象都已经非常熟悉了),迭代器对象里包含着每一个匹配到的元素的详细信息。matchAll
方法接收一个正则表达式的参数,且正则表达式参数必须带有g(全局匹配),否则会报错。
const name = "iceCode";
const iteratorObj = name.matchAll(/[a-z]/g);
//matchAll返回的迭代器对象使用.next().value查看每一条匹配元素数据
console.log(iteratorObj.next().value);//[ 'i', index: 0, input: 'iceCode', groups: undefined ]
console.log(iteratorObj.next().value);//[ 'c', index: 1, input: 'iceCode', groups: undefined ]
console.log(iteratorObj.next().value);//[ 'e', index: 2, input: 'iceCode', groups: undefined ]
console.log(iteratorObj.next().value);//[ 'o', index: 4, input: 'iceCode', groups: undefined ]
console.log(iteratorObj.next().value);//[ 'd', index: 5, input: 'iceCode', groups: undefined ]
console.log(iteratorObj.next().value);//[ 'e', index: 6, input: 'iceCode', groups: undefined ]
//同时也可以使用展开运算符 使其改变为二维数组,看着比使用next更方便写,当然迭代器对象本就可以使用for..of..遍历
console.log([...iteratorObj]);
//[
// [ 'i', index: 0, input: 'iceCode', groups: undefined ],
// [ 'c', index: 1, input: 'iceCode', groups: undefined ],
// [ 'e', index: 2, input: 'iceCode', groups: undefined ],
// [ 'o', index: 4, input: 'iceCode', groups: undefined ],
// [ 'd', index: 5, input: 'iceCode', groups: undefined ],
// [ 'e', index: 6, input: 'iceCode', groups: undefined ]
//]
search 返回检索与正则表达式匹配的索引
此方法与match
类似,不过match
返回的是匹配到的字符,而search
返回的是匹配到第一个的元素的索引,无论是否添加g(全局检索)都只会返回第一个查找到元素的索引,没有找到则返回-1。接受一个正则表示的参数。
const name = "iceCode";
//正则表达式是否添加全局检索,都只会匹配第一个所查找到的元素的索引
console.log(name.search(/[A-Z]/));//3
console.log(name.search(/[a-z]/g));//0
repeat 复制
repeat
会接收一个Number
类型的参数,范围0~+Infinity
,为复制本身的字符的次数
const name = "iceCode";
//单纯的就是重复复制本身字符串
console.log(name.repeat(3));//iceCodeiceCodeiceCode
console.log(`name重复了5次${name.repeat(5)}`);//name重复了5次iceCodeiceCodeiceCodeiceCodeiceCode
//负数则会报错
console.log(name.repeat(-1));//error
toWellFormed 字符串的所有单独代理项都被替换为 Unicode 替换字符 U+FFFD
此方法兼容极差,谨慎使用。Node版本需要20.0.0+
toWellFormed()
迭代字符串的码元,并将任何单独代理项替换为 Unicode 替换字符 U+FFFD �
。这确保了返回的字符串格式正确并可用于期望正确格式字符串的函数,比如 encodeURI
。由于引擎能够直接访问字符串的内部表示,与自定义实现相比 toWellFormed()
更高效。
当在某些上下文中使用格式不正确的字符串时,例如 TextEncoder
,它们会自动转换为使用相同替换字符的格式正确的字符串。当单独代理项被呈现时,它们也会呈现为替换字符(一个带有问号的钻石形状)。
也可以简单的理解为toWellFormed
相当于一项字符串转码前的安全转换
const strings = [
// 单独的前导代理
"ab\uD800",
"ab\uD800c",
// 单独的后尾代理
"\uDFFFab",
"c\uDFFFab",
// 格式正确
"abc",
"ab\uD83D\uDE04c",
];
//这里如果有错误的格式会自动转换成�
for (const str of strings) {
console.log(str.toWellFormed());
}
// Logs:
// "ab�"
// "ab�c"
// "�ab"
// "c�ab"
// "abc"
// "ab😄c"
//如果这里不使用toWellFormed直接使用encodeURI进行转码,就会报错
for (const str of strings) {
console.log(encodeURI(str));
}
//URI malformed
//使用toWellFormed之后再使用encodeURI进行转码之后就不会出现这个错误
for (const str of strings) {
console.log(encodeURI(str.toWellFormed()));
}
//ab%EF%BF%BD
//ab%EF%BF%BDc
//%EF%BF%BDab
//c%EF%BF%BDab
//abc
//ab%F0%9F%98%84c
isWellFormed 判断该字符串是否包含单独代理
此方法兼容极差,谨慎使用。Node版本需要20.0.0+
同toWellFormed
方法类似,也可以简单额理解为转码前的一个安全判断
const strings = [
// 单独的前导代理
"ab\uD800",
"ab\uD800c",
// 单独的后尾代理
"\uDFFFab",
"c\uDFFFab",
// 格式正确
"abc",
"ab\uD83D\uDE04c",
];
//当不包含单独代理的字符,无法通过判断
for (const str of strings) {
console.log(str.isWellFormed());
}
// 输出:
// false
// false
// false
// false
// true
// true
localeCompare 字符串之间的比较
localeCompare
方法返回一个数字,用于表示比较字符串在排序顺序中,在给定的字符串之前还是之后或者相同。在支持 Intl.Collator
API 的实现中,该方法仅是调用了 Intl.Collator
方法。
localeCompare
方法接收三个参数,第一个参数是要比较的字符串,第二个参数是表示缩写语言代码的字符串,第三个参数是一个配置对象,为对应于 Intl.Collator()
构造函数的参数。 了解更多点击这里
const a = "réservé";
const b = "RESERVE";
//当指定了语言类型已经排序方式时,与默认排序会有一定差异
console.log(a.localeCompare(b));//-1
console.log(a.localeCompare(b, "en", { sensitivity: "base" }));//0
console.log("ä".localeCompare("z", "de")); // 负值 -1:在德语中,ä 排在 z 之前
console.log("ä".localeCompare("z", "sv")); // 正值 1:在瑞典语中,ä 排在 z 之后
//可以对大小写不敏感排序
const items = ["réservé", "Premier", "Cliché", "communiqué", "café", "Adieu"];
items.sort((a, b) => a.localeCompare(b, "fr", { ignorePunctuation: true }));
console.log(items);//[ 'Adieu', 'café', 'Cliché', 'communiqué', 'Premier', 'réservé' ]
toString 返回字符串的值
String
对象重写了 Object
的 toString
方法;对于 String
值,toString
方法返回字符串本身(如果它是原始值)或 String
对象封装的字符串。它的实现与String.prototype.valueOf()
完全相同。当一个 String
对象在期望字符串的上下文中使用时(比如在模板字面量中),JavaScript 会自动调用 toString()
方法。
//在重写之前调用toString会返回字符串的值
console.log(new String("Code").toString());//code
//这里对String的toString进行重写
String.prototype.toString = function () {
//切记return的时候不要使用模板字符串,否则会栈溢出,因为模板字符串会自动调用toString方法
return this + "的toString被自动调用了";
};
//这里正常是不会调用toString方法的
console.log(new String("Code"));//[String: 'Code']
//在使用模字符串的时候会自动调用toString方法
console.log(`${new String("iceCode")}`);//iceCode的toString被自动调用了
valueOf 返回字符串的值
在String
中valueO
f与toString
是等价的,此方法通常由 JavaScript
在内部调用,而不是在代码中显式调用。
const name = "iceCode";
//改变valueOf方法
String.prototype.valueOf = function () {
return this + "的valueOf被调用了";
};
//在使用new Stong创建字符串的时候会自动调用valueOf 然后在this为new String对象,当返回这个this的时候
//会再次调用valueOf,最终会导致栈溢出
console.log(new String("Code").valueOf());//Error:Maximum call stack size exceeded
//字面量创建的字符串则不会出现这种情况
console.log(name.valueOf());//iceCode的valueOf被调用了
String.raw 模板字符串的标签函数
String.raw
的作用类似于 Python
中的 r
前缀或 C#
中用于字符串字面量的 @
前缀。它用于获取模板字符串的原始字符串形式——即,变量(例如 ${foo}
)会被替换处理,但转义序列(例如 \n
)不会被处理。
它的使用方法有个两种,一种是后面直接跟模板字符串(比较常用),是js函调用的一种特殊方法(前段时间吵得沸沸腾腾的react
调用SQL
的写法就是这种)。另外一种是括号形式的函数调用,接收一个以上参数,第一个参数为一个对象,对象有一个raw
属性,属性值可以是任意类型(除了null,undefined,但建议是类数组对象),从第二个参数开始为包含的替换表达式对应的值。
//先看第一种模板字符串调用
const name = "iceCode";
//如果不使用raw 可以看出字符串的写的路径\都消失了,在字符串中\是转义符的意思,所以会消失
//这里变量没出来也是因为$符被转译了,无法识别出模板字符串中的变量
console.log(`c:\Admin\password\${name}`);//c:Adminpassword${name}
//当使用了raw方法后,\符号后面的字母将不会再转义,但是$符依旧被转义了,可以空一格或者$符前面加个字母就行
console.log(String.raw`c:\Admin\password\${name}`);//c:\Admin\password\${name}
//这里如果再\符号后面写数字的时候是会报错的:模板字符串中无法使用八进制转义符序列
console.log(`c:\Admin\password\12345`);//Error:Octal escape sequences are not allowed in template strings.
//当使用了raw方法后将不会再转义,所以可以正常显示
console.log(String.raw`c:\Admin\password\12345`);//c:\Admin\password\12345
//在正常打印中\f,\n,\r,\v都有特殊的意义无法显示出来(将\转义成普通斜杠是可以显示出来的)
console.log(`c:\fn\nd\rw\vr`);
//c:
//n
//w
//r
//使用raw可以避免这些问题
console.log(String.raw`c:\fn\nd\rw\vr`);//c:\fn\nd\rw\vr
//括号函数调用
第一个参数必须是一个对象,对象里必须有一个raw属性,这里可以看出是将数组中的字符串合并并返回
console.log(String.raw({ raw: [name, "3234"] }));//iceCode3234
//这里raw的值是一个字符串,但是会被分割为一个数组:['i','c','e','C','o','d','e'],没有传入第二个以后的参数会返回原字符串
console.log(String.raw({ raw: name }));//iceCode
//当如果传入第二个以后的参数会插入到数组元素之间再合并
console.log(String.raw({ raw: name }, 1, 2, 3, 4, 5));//i1c2e3C4o5de
//如果插入过多,数组元素的间隙不够则会舍弃
console.log(String.raw({ raw: [name, "asdf"] }, 1, 2, 3, 4, 5));//iceCode1asdf
String.fromCharCode 返回指定的 UTF-16 码元序列创建的字符串
接收n个参数,为UTF-16
码元,范围在0~65535(0xFFFF)
之间,可以将他们转换为指定的字符
//返回UTF-16码元对应的字符
console.log(String.fromCharCode(189, 43, 190, 61));//½+¾=
//在 UTF-16 中,补充字符需要两个码元(即一个代理对)
console.log(String.fromCharCode(55356, 57091));//🌃
console.log(String.fromCharCode(0xd834, 0xdf06, 0x61, 0xd834, 0xdf07));//𝌆a𝌇
String.fromCodePoint 根据指定的码位序列返回一个字符串
接收n个参数,为Unicode
码位,范围在0~0x10FFFF
之间,返回通过使用指定的码位序列创建的字符串
//返回码位对应的字符
console.log(String.fromCodePoint(9731, 9733, 9842, 0x2f804))//☃★♲你
//与fromCharCode对比
console.log(String.fromCharCode(55356, 57091));//🌃
console.log(String.fromCodePoint(0x1f303));//🌃
不再推荐,但浏览器也许还支持的一些字符串方法(14个)
fontsize 创建font元素,并指定字体大小
对于 fontsize()
方法来说,<font>
元素本身在 HTML5 中已被移除,不应再使用。接收一个1-7之间的参数,来创建一个指定大小的字符元素
const name = "iceCode";
console.log(name.fontsize(5));//<font size="5">iceCode</font>
fontcolor 创建font元素,并指定字体颜色
同fontsize
方法描述一样,接收一个颜色的字面量或十六进制的RGB颜色参数,来创建一个指定颜色的字符元素
const name = "iceCode";
console.log(name.fontcolor("red"));//<font color="red">iceCode</font>
console.log(name.fontcolor("00ff66"));//<font color="#00ff66">iceCode</font>
fixed 创建一个tt元素
fixed
会创建一个tt
元素,并将指定字符嵌入元素内,tt
元素会致该字符串以等宽字体显示。
const name = "iceCode";
console.log(name.fixed());//<tt>iceCode</tt>
big 创建big元素
big
方法用于创建一个big
元素,并将指定字符嵌入元素内,将以大号字体显示
const name = "iceCode";
console.log(name.big());//<big>iceCode</big>
small 创建small元素
small
方法用于创建一个small
元素,并将指定字符嵌入元素内,将以小号字体显示
const name = "iceCode";
console.log(name.small());//<small>iceCode</small>
anchor 创建a元素,并指定name
anchor
方法用于创建一个a
元素,并将指定字符嵌入元素内,接收一个字符串参数,为name
属性的值
const name = "iceCode";
console.log(name.anchor('锚点'));//<a name="锚点">iceCode</a>
link 创建a元素,并指定href
link
方法用于创建一个a
元素,并将指定字符嵌入元素内,接收一个字符串参数,为href
属性的链接值
const name = "iceCode";
console.log(name.link('https://www.baidu.com/'));//<a href="https://www.baidu.com/">iceCode</a>
blink 创建blink元素
blink
方法用于创建一个blink
元素,并将指定的字符嵌入元素内。blink
元素在旧版浏览器中的作用是闪烁,已经被现代浏览器删除。
const name = "iceCode";
console.log(name.blink());//<blink>iceCode</blink>
bold 创建b元素
bold
方法用于创建一个b
元素,并将指定字符嵌入元素内,将以粗体显示
const name = "iceCode";
console.log(name.bold());//<b>iceCode</b>
italics 创建i元素
italics
方法用于创建一个i
元素,并将指定字符嵌入元素内,将以斜体显示
const name = "iceCode";
console.log(name.italics());//<i>iceCode</i>
strike 创建strike元素
strike
方法用于创建一个strike
元素,并将指定字符嵌入元素内,将以删除线的形式显示
const name = "iceCode";
console.log(name.strike());//<strike>iceCode</strike>
sup 创建sup元素
sup
方法用于创建一个sup
元素,并将指定字符嵌入元素内,将以上标的形式显示
const name = "iceCode";
console.log(name.sup());//<sup>iceCode</sup>
sub 创建sub元素
sub
方法用于创建一个sub
元素,并将指定字符嵌入元素内,将以下标的形式显示
const name = "iceCode";
console.log(name.sub());//<sub>iceCode</sub>
substr 返回该字符串的一部分
substr
会返回字符串的一部分,接收两个参数,第一个参数为开始的索引值,第二个参数为要返回多少位字符的个数。substr
不属于 ECMAScript
主要规范。所以这里也不推荐,推荐使用标准的substring
和slice
方法
const name = "iceCode";
//可以以下列几种方式进行截取
console.log(name.substr(2, 4));//eCod
console.log(name.substr(-3));//ode
console.log(name.substr(-2, 1));//d
不推荐的方法除了substr之外,基本是HTML的包装方法,但这些包装方法已经被弃用,并且仅为了兼容性而标准化。推荐使用document.createElement方法代替
最后
String
的方法虽多,但是平时经常使用中的方法却寥寥无几。除了一些不推荐的方法以外,大多String
方法会针对不同国家不同地区进行不同的编码,对UTF-16
和和Unicode
编码的一些处理,也不是我们日常数据处理或者开发中所需要的,这些方法大可浏览一遍即可。
另外对字符串的处理一般少不了正则表达式,所以对于正则表达式使用还是有必要会一些的