盘点字符串String方法

盘点字符串String方法

前言

在js中,String类型是我们在处理数据时最常接触的类型之一了。但是String类型已经存在惊人的51个方法了,不知道你是用过几种。

String类型也是最万能的,在js中任何类型都可以转成字符串类型,但反过来就不一定了,所以这好像理解了为什么平平无奇的String类型可以有这么多方法了。

这么多方法当然也存在一些不被推荐的方法,准备删除或出于兼容性而保留的,但是部分浏览器也还支持。以下会单独分开说,可以作为了解。

1. 推荐方法(37个)

1.1 ⭐includes 查找一组字符串中是否存在某个字符

此方法用来查找一组字符串中是否存在某个字符,区分大小写。接收两个参数:

第一个为希望查找的字符,并且不能是正则表达式,所有传入的参数都将自动转为字符串

第二个参数为要从哪个位置开始查找(可选),默认为0,返回一个布尔值。

1
2
3
4
5
6
7
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

1.2 ⭐indexOf 查找一组字符串中的某个字符,并返回索引

这个方法同includes差不多,同样会查找一组字符串中是否存在某个字符,不同的是**indexOf是返回一个索引,而includes返回的是一个布尔值**。接收两个参数:

第一个为希望查找的字符,规则同includes

第二个为想要从哪个地方查找(可选),返回查找字符第一次出现的索引,没找到则返回-1。

1
2
3
4
5
6
7
8
9
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

1.3 lastIndexOf indexOf的反向查找版

lastIndexOfindexOf的区别就是,lastIndexOf是从后往前找,并且查找到这组字符串中唯一值的结果不会改变(当查找空字符串时,返回的结果可能会有一丝变化),接收参数与indexOf相同。返回查找字符串最后一次出现的索引,没找到为-1

1
2
3
4
5
6
7
8
9
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

1.4 padStart 从前往后重复填充字符到指定长度

此方法会重复填充给定的字符到指定长度,接收两个参数:

第一个为指定长度,

第二个是要填充的字符,

返回一个最终指定长度并包含重复填充字符的字符串,如果第一个指定的长度小于当前字符的长度则返回原字符串

1
2
3
4
5
6
7
8
//看上面文字描述可能有点不太好理解,直接看代码就非常好理解了

//当前定义的字符串长度为7
const name = "iceCode";
//这里指定了长度为20,然后填充指定字符'e'最后返回的是一个长度为20的字符串,从前往后填充
console.log(name.padStart(20, "e"));//eeeeeeeeeeeeeiceCode
//当填充长度小于当前字符串长度,则返回当前字符串
console.log(name.padStart(5, "666"));//iceCode

1.5 padEnd 从后往前重复填充字符到指定长度

这个方法同padStart几乎类似,差别就是这个方法是从后往前填充。接收参数同padStart相同,返回值的规则与padStart相同

1
2
3
4
5
const name = "iceCode";
//返回一个长度为20的字符串,要填充的字符是从后往前填充
console.log(name.padEnd(20, "e"));//iceCodeeeeeeeeeeeeee
//指定长度没有当前字符长,同样会返回当前字符串
console.log(name.padEnd(5, "666"));//iceCode

1.6 ⭐replace 替换指定字符

replace只会替换第一个找到匹配字符的元素然后进行替换,接收两个参数:

第一个为要被替换的字符(任何不是String类型的参数,都会被转成String处理),可以是正则表达式

第二个为替换为的字符,返回被替换后一个新的字符串。

1
2
3
4
5
6
7
8
9
10
11
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,初来乍到,还请多多关照。

另外替换为的字符也可以是特殊替换模式,不过需要使用正则表达式进行查找

image.png

  1. 使用 $& 插入匹配的子字符串:
1
2
3
4
const name = "iceCode";
//这里$&就是匹配到的字符,并拼接上新的字符替换掉它,最后的结果就是Hi,iceCode
//是这样替换的 ice->Hi,ice
console.log(name.replace(/ice/g, "Hi,$&"));//Hi,iceCode
  1. 使用 $$ 插入字符串$:
1
2
3
const name = "iceCode";
//这里很好理解 两个$和一个$效果是一样的
console.log(name.replace(/ice/g, "$$"));//$Code
  1. 使用 `$``a(反引号)插入匹配子字符串之前的字符串片段:
1
2
3
const name = "iceCode";
//使用$`代表了匹配到的字符之前所有的字符 这里代表了iceCo 所以是将de的位置替换为了iceCo
console.log(name.replace(/de/g, "$`"));//iceCoiceCo
  1. 使用 $'(单引号)插入匹配子字符串之后的字符串片段:
1
2
3
const name = "iceCode";
//使用$'代表了匹配到的字符之后所有的字符 这里代表了Code 所以是将ice的位置替换为了Code
console.log(name.replace(/ice/g, "$'"));//CodeCode
  1. 使用 $n 插入第 n 个捕获组:
1
2
3
4
5
6
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
  1. 使用$Name 插入名称为 Name 的命名捕获组:
    这个例子与上面的例子类似,只是使用了命名捕获组。以下是相应的代码:
1
2
3
4
5
const name = "iceCode";
//正则表达式中?<变量>... 这里?后的变量名为命名捕获组的名,可以在替换中使用,...代表了命名捕获组存的数据
//使用的时候$<变量> 就可以了
//这里匹配到了iceCode $<im>就是ice 拼接d,CODE 最后的结果就是iced,CODE
console.log(name.replace(/(?<im>ice)(Code)/g, "$<im>d,CODE"));//iced,CODE

这里对正则表达式的掌握还是有一些的,正则表达式

另外,替换为的参数也可以是一个回调函数,传入一个参数,是匹配到的元素,这个回调函数可以作为一个简单工厂函数来操作

1
2
3
const name = "iceCode";
//这里将匹配到的字符转成大写在返回出来替换原来字符
console.log(name.replace("ice", (v) => v.toUpperCase()));//ICECode

1.7 replaceAll 替换一段字符串中全部指定字符

replaceAll兼容性有些不太好,需要node15以上,老项目中谨慎使用

此方法相当于replace的补全版,因为replace在不使用正则的情况下,只能匹配到一段字符串中第一个找到的字符,对于要替换所查找到的所有指定字符时可能会有些麻烦,使用replaceAll可以方便的替换所有指定字符。参数和指定被替换的字符与repalce相同,这里就不多写了

1
2
3
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.

1.8 ⭐slice 截取字符串

slice截取对应索引的字符串,并返回一个新的字符串,不会改变原数组。接收两个参数:

第一个为开始截取的索引位置,

第二个为截取结束位置的索引(可选),

不包括第二个参数索引位置的元素,返回一个新的截取后的字符串。

1
2
3
4
5
6
7
const name = "iceCode";
//只传一个参数,会从传入的索引位置截取到最后
console.log(name.slice(1));//ceCode
//不包含第二个索引位置的字符
console.log(name.slice(1, 5));//ceCo
//可以为负数,如果第一个小于第二个参数则会返回空
console.log(name.slice(-5, -1));//eCod

1.9 ⭐substring 截取字符串

substringslice效果相同,区别在于他们传的参数,不同参数会有不同区别。同样接受两个参数,参数同样的效果,同样不改变原数组,同样返回要给新的截取后的字符串

1
2
3
4
5
6
7
8
9
10
11
//效果都知道,这里只说它们的区别

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.substring(1, 3));//ce
console.log(name.slice(3, 1));//''

1.10 ⭐split 指定字符分割成数组

split可以将字符串以指定元素分割成一个数组,可以说是String方法中比较常用的一个了,接收两个参数:

第一个为指定字符,对字符串进行分割为数组,

第二个为分割的数组最大长度,返回一个数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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' ]

1.11⭐ toUpperCase 将英文字符串转换成大写

toUpperCase作用很简单,就是将英文字符串转换成大写英文,如果是汉字则返回原字符串

1
2
3
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里可以发现只是将英文转换了,汉字是不会改变的
console.log(zhIntroduce.toUpperCase());//我是ICECODE,初来乍到,还请多多关照。

1.12 ⭐toLowerCase 将英文字符串转换成小写字符串

toLowerCase作用一样很简单,就是将英文字符串转换成小写英文,如果是汉字则返回原字符串

1
2
3
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里可以发现只是将英文转换了,汉字是不会改变的
console.log(zhIntroduce.toLowerCase());//我是icecode,初来乍到,还请多多关照。

1.13 toLocaleUpperCase 根据特定时区将字符串转化成大写

toLocaleUpperCase根据特定区域设置的大小写映射规则,将字符串转换为大写形式,接收一个可选的参数,参数规则参考Intl 主页上的参数描述。大多情况下与toUpperCase一致,只有个别地区的大小写会有些区别。

1
2
3
4
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//只有少数语言会有细微差距
console.log(zhIntroduce.toLocaleUpperCase('en-US'));//我是ICECODE,初来乍到,还请多多关照。
console.log("Gesäß".toLocaleUpperCase());GESÄSS

1.14 toLocaleLowerCase 根据特定时区将字符串转化成小写

toLocaleLowerCase根据特定区域设置的大小写映射规则,将字符串转换为小写形式,接收一个可选参数,参数规则参考Intl 主页上的参数描述。大多情况下与toLowerCase一致,只有个别地区的大小写会有些区别。

1
2
3
4
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//只有少数语言会有细微差距
console.log(zhIntroduce.toLocaleLowerCase('en-US'));//我是icecode,初来乍到,还请多多关照。
console.log("Gesäß".toLocaleLowerCase());gesäß

1.15 ⭐trim 去除两端空白字符

trim就非常很好理解,就是去除两端的空格的,一般在表单输入的时候,有可能会有多输入空白字符,可以使用trim对两端空白字符进行剔除

1
2
3
const name = "   iceCode    ";
//将两端的空白字符剔除
console.log(name.trim());//iceCode

1.16 ⭐trimStart、trimEnd 剔除开头空白字符和剔除结尾空白字符

trim是一次性剔除两端空白字符,显得没有那么灵活。这里trimStart、trimEnd分别是剔除开头空白字符和剔除结尾空白字符,可以在使用的时候更加灵活。另外trimLeft、trimRight是trimStart、trimEnd的别名

1
2
3
4
5
6
const name = "   iceCode    ";
//使用别名和它们是相同的效果
console.log(name.trimStart());//'iceCode '
console.log(name.trimLeft());//'iceCode '
console.log(name.trimEnd());//' iceCode'
console.log(name.trimRight());//' iceCode'

1.17 ⭐concat 拼接字符串

concat可以对多个字符串相互拼接,接收n个任意类型参数,参数为要拼接的字符串或其他类型参数。这个方法就好比是游泳比赛的救生员一样。因为字符串与任何类型数相加最后都是字符串,这个方法几乎用不到。

1
2
3
4
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
const name = "iceCode";
//对多个参数进行字符拼接,结果与 字符串+<任意类型数据>是一样的
console.log(zhIntroduce.concat(name, 2, ["666"]));//我是iceCode,初来乍到,还请多多关照。iceCode2666

1.18 ⭐startsWith 判断一个字符串是否以指定字符串开头

startsWith接收两个参数,

第一个为要查找结尾的字符,可以是任意类型(正则除外),但都会默认转换成字符串,

第二个参数为开始的索引,返回个布尔值

1
2
3
4
5
6
7
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

1.19 ⭐endsWith 判断一个字符串是否以指定字符串结尾

endsWith接收两个参数,

第一个为要查找结尾的字符,可以是任意类型(正则除外),但都会默认转换成字符串,

第二个参数为结尾的索引(最后一个字符的索引加 1),返回个布尔值

1
2
3
4
5
6
7
const zhIntroduce = "我是iceCode,初来乍到,还请多多关照。";
//这里结尾的是。 所以为true
console.log(zhIntroduce.endsWith("。"));//true
//这里传入第二个参数,到索引为10的位置就结束,所以,也是对的
console.log(zhIntroduce.endsWith(",", 10));//true
//这里,是英文状态的,所以为false
console.log(zhIntroduce.endsWith(",", 10));//false

1.20 ⭐charAt 返回给定的索引的字符

charAt返回一个由给定索引处的单个 UTF-16 码元构成的新字符串。接收一个参数,为要找元素的索引值。返回要找的元素。

1
2
3
4
5
6
7
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));//�

1.21 charCodeAt 给定索引处的 UTF-16 码元

此方法与charAt相似,只是返回值不同,charAt返回的是由UTF-16码元构成的新字符串,而charCodeAt返回的则直接是一个码元,其值介于 065535 之间。

1
2
3
4
5
6
7
8
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

1.22 normalize 返回字符串 Unicode 标准化形式

了解Unicode可以查看:Unicode字符表 (rapidtables.org)

normalize返回一个Unicode标准化形式,接收一个可选参数,参数值为:

  • NFC:规范分解,然后进行规范组合。
  • NFD:规范分解。
  • NFKC:兼容分解,然后进行规范组合。
  • NFKD:兼容分解。

如果normalize没有传入参数(undefined),则按照NFC来解析。正常来说一个Unicode编码在使用normalize(不传参)和不使用normalize的时候得到的结果大致是一样的。

1
2
3
4
5
6
7
8
9
//这里随便找了几个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Ž

1.23 codePointAt 给定索引开始的字符的 Unicode 码位值

该整数是从给定索引开始的字符的 Unicode 码位值。请注意,索引仍然基于 UTF-16 码元,而不是 Unicode 码位。有关 Unicode 的信息,请参阅 UTF-16 字符、Unicode 码位和字素簇

1
2
3
4
5
6
7
8
9
10
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

1.24 at 查找索引位置的字符

此方法兼容性一般,node版本需要16.6.0以上,生产环境谨慎使用 字符串的at方法与数组的at方法类似,返回结果如果有与charAt一致,接收一个参数,为一个整数,可以是正整数也可以为负数,返回指定位置的单个 UTF-16 码元组成的字符,负数的时候从后往前找。

1
2
3
4
5
6
7
8
9
10
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));//�

1.25 ⭐match 检索与正则表达式匹配的结果

match方法会检索与正则表达式匹配的结果,接收一个正则表达式的参数,返回一个数组,如果正则表达式中没有使用g(全局)检索,数组中则会返回检索到元素的详细信息,如果添加了g,则会返回一个包含所有匹配到元素的数组

1
2
3
4
5
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' ]

1.26 matchAll 返回检索与正则表达式匹配结果的一个迭代器对象

此方法与match方法很像,但是返回值却大不相同,match方法返回的是一个正常的数组,matchAll则是一个迭代器对象(想必对迭代器对象都已经非常熟悉了),迭代器对象里包含着每一个匹配到的元素的详细信息。matchAll方法接收一个正则表达式的参数,且正则表达式参数必须带有g(全局匹配),否则会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 ]
//]

1.27⭐ search 返回检索与正则表达式匹配的索引

此方法与match类似,不过match返回的是匹配到的字符,而search返回的是匹配到第一个的元素的索引,无论是否添加g(全局检索)都只会返回第一个查找到元素的索引,没有找到则返回-1。接受一个正则表示的参数。

1
2
3
4
const name = "iceCode";
//正则表达式是否添加全局检索,都只会匹配第一个所查找到的元素的索引
console.log(name.search(/[A-Z]/));//3
console.log(name.search(/[a-z]/g));//0

1.28 ⭐repeat 复制

repeat会接收一个Number类型的参数,范围0~+Infinity,为复制本身的字符的次数

1
2
3
4
5
6
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

1.29 toWellFormed 字符串的所有单独代理项都被替换为 Unicode 替换字符 U+FFFD

此方法兼容极差,谨慎使用。Node版本需要20.0.0+

toWellFormed() 迭代字符串的码元,并将任何单独代理项替换为 Unicode 替换字符 U+FFFD 。这确保了返回的字符串格式正确并可用于期望正确格式字符串的函数,比如 encodeURI。由于引擎能够直接访问字符串的内部表示,与自定义实现相比 toWellFormed() 更高效。

当在某些上下文中使用格式不正确的字符串时,例如 TextEncoder,它们会自动转换为使用相同替换字符的格式正确的字符串。当单独代理项被呈现时,它们也会呈现为替换字符(一个带有问号的钻石形状)。

也可以简单的理解为toWellFormed相当于一项字符串转码前的安全转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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

1.30 isWellFormed 判断该字符串是否包含单独代理

此方法兼容极差,谨慎使用。Node版本需要20.0.0+

toWellFormed方法类似,也可以简单额理解为转码前的一个安全判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

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

1.31 localeCompare 字符串之间的比较

localeCompare 方法返回一个数字,用于表示比较字符串在排序顺序中,在给定的字符串之前还是之后或者相同。在支持 Intl.Collator API 的实现中,该方法仅是调用了 Intl.Collator 方法。

localeCompare 方法接收三个参数,

第一个参数是要比较的字符串,

第二个参数是表示缩写语言代码的字符串,

第三个参数是一个配置对象,为对应于 Intl.Collator() 构造函数的参数。 了解更多点击这里

1
2
3
4
5
6
7
8
9
10
11
12
13
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é' ]

1.32 ⭐toString 返回字符串的值

String 对象重写了 ObjecttoString 方法;对于 String 值,toString 方法返回字符串本身(如果它是原始值)或 String 对象封装的字符串。它的实现与String.prototype.valueOf() 完全相同。当一个 String 对象在期望字符串的上下文中使用时(比如在模板字面量中),JavaScript 会自动调用 toString() 方法。

1
2
3
4
5
6
7
8
9
10
11
12
//在重写之前调用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被自动调用了

1.33 ⭐valueOf 返回字符串的值

StringvalueOftoString是等价的,此方法通常由 JavaScript 在内部调用,而不是在代码中显式调用。

1
2
3
4
5
6
7
8
9
10
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被调用了

1.34 String.raw 模板字符串的标签函数

String.raw的作用类似于 Python 中的 r 前缀或 C# 中用于字符串字面量的 @ 前缀。它用于获取模板字符串的原始字符串形式——即,变量(例如 ${foo})会被替换处理,但转义序列(例如 \n)不会被处理。

它的使用方法有个两种,一种是后面直接跟模板字符串(比较常用),是js函调用的一种特殊方法(前段时间吵得沸沸腾腾的react调用SQL的写法就是这种)。另外一种是括号形式的函数调用,接收一个以上参数,第一个参数为一个对象,对象有一个raw属性,属性值可以是任意类型(除了null,undefined,但建议是类数组对象),从第二个参数开始为包含的替换表达式对应的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//先看第一种模板字符串调用

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

1.35 String.fromCharCode 返回指定的 UTF-16 码元序列创建的字符串

接收n个参数,为UTF-16码元,范围在0~65535(0xFFFF)之间,可以将他们转换为指定的字符

1
2
3
4
5
//返回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𝌇

1.36 String.fromCodePoint 根据指定的码位序列返回一个字符串

接收n个参数,为Unicode 码位,范围在0~0x10FFFF之间,返回通过使用指定的码位序列创建的字符串

1
2
3
4
5
6
//返回码位对应的字符
console.log(String.fromCodePoint(9731, 9733, 9842, 0x2f804))//☃★♲你

//与fromCharCode对比
console.log(String.fromCharCode(55356, 57091));//🌃
console.log(String.fromCodePoint(0x1f303));//🌃

2. 不再推荐(14个)

2.1 fontsize 创建font元素,并指定字体大小

对于 fontsize() 方法来说,<font> 元素本身在 HTML5 中已被移除,不应再使用。接收一个1-7之间的参数,来创建一个指定大小的字符元素

1
2
const name = "iceCode";
console.log(name.fontsize(5));//<font size="5">iceCode</font>

2.2 fontcolor 创建font元素,并指定字体颜色

fontsize方法描述一样,接收一个颜色的字面量或十六进制的RGB颜色参数,来创建一个指定颜色的字符元素

1
2
3
const name = "iceCode";
console.log(name.fontcolor("red"));//<font color="red">iceCode</font>
console.log(name.fontcolor("00ff66"));//<font color="#00ff66">iceCode</font>

2.3 fixed 创建一个tt元素

fixed会创建一个tt元素,并将指定字符嵌入元素内,tt元素会致该字符串以等宽字体显示。

1
2
const name = "iceCode";
console.log(name.fixed());//<tt>iceCode</tt>

2.4 big 创建big元素

big方法用于创建一个big元素,并将指定字符嵌入元素内,将以大号字体显示

1
2
const name = "iceCode";
console.log(name.big());//<big>iceCode</big>

2.5 small 创建small元素

small方法用于创建一个small元素,并将指定字符嵌入元素内,将以小号字体显示

1
2
const name = "iceCode";
console.log(name.small());//<small>iceCode</small>

2.6 anchor 创建a元素,并指定name

anchor方法用于创建一个a元素,并将指定字符嵌入元素内,接收一个字符串参数,为name属性的值

1
2
const name = "iceCode";
console.log(name.anchor('锚点'));//<a name="锚点">iceCode</a>

link方法用于创建一个a元素,并将指定字符嵌入元素内,接收一个字符串参数,为href属性的链接值

1
2
const name = "iceCode";
console.log(name.link('https://www.baidu.com/'));//<a href="https://www.baidu.com/">iceCode</a>

blink方法用于创建一个blink元素,并将指定的字符嵌入元素内。blink元素在旧版浏览器中的作用是闪烁,已经被现代浏览器删除。

1
2
const name = "iceCode";
console.log(name.blink());//<blink>iceCode</blink>

2.9 bold 创建b元素

bold方法用于创建一个b元素,并将指定字符嵌入元素内,将以粗体显示

1
2
const name = "iceCode";
console.log(name.bold());//<b>iceCode</b>

2.10 italics 创建i元素

italics方法用于创建一个i元素,并将指定字符嵌入元素内,将以斜体显示

1
2
const name = "iceCode";
console.log(name.italics());//<i>iceCode</i>

2.11 strike 创建strike元素

strike方法用于创建一个strike元素,并将指定字符嵌入元素内,将以删除线的形式显示

1
2
const name = "iceCode";
console.log(name.strike());//<strike>iceCode</strike>

2.12 sup 创建sup元素

sup方法用于创建一个sup元素,并将指定字符嵌入元素内,将以上标的形式显示

1
2
const name = "iceCode";
console.log(name.sup());//<sup>iceCode</sup>

2.13 sub 创建sub元素

sub方法用于创建一个sub元素,并将指定字符嵌入元素内,将以下标的形式显示

1
2
const name = "iceCode";
console.log(name.sub());//<sub>iceCode</sub>

2.14 substr 返回该字符串的一部分

substr会返回字符串的一部分,接收两个参数,

第一个参数为开始的索引值,

第二个参数为要返回多少位字符的个数。

substr不属于 ECMAScript 主要规范。所以这里也不推荐,推荐使用标准的substringslice方法

1
2
3
4
5
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方法代替

3. 最后

String的方法虽多,但是平时经常使用中的方法却寥寥无几。除了一些不推荐的方法以外,大多String方法会针对不同国家不同地区进行不同的编码,对UTF-16和和Unicode编码的一些处理,也不是我们日常数据处理或者开发中所需要的,这些方法大可浏览一遍即可。

另外对字符串的处理一般少不了正则表达式,所以对于正则表达式使用还是有必要会一些的

作者:iceCode

链接:https://juejin.cn/post/7300731450597277732

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。