字符串的新增方法
字符串的新增方法
String.fromCodePoint()
-
ES5 提供
String.fromCharCode()
方法,用于从 Unicode 码点返回对应字符,但是这个方法不能识别码点大于0xFFFF
的字符String.fromCharCode(0x20BB7) // "ஷ" 最高位2被舍弃了,最后返回码点U+0BB7对应的字符,而不是码点U+20BB7对应的字符
-
ES6 提供了
String.fromCodePoint()
方法,可以识别大于0xFFFF
的字符,弥补了String.fromCharCode()
方法的不足String.fromCodePoint(0x20BB7) // "????" String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y' // true 如果String.fromCodePoint方法有多个参数,则它们会被合并成一个字符串返回
-
fromCodePoint
方法定义在String
对象上,而codePointAt
方法定义在字符串的实例对象上
实例方法:codePointAt()
-
JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为
2
个字节。对于那些需要4
个字节储存的字符(Unicode 码点大于0xFFFF
的字符),JavaScript 会认为它们是两个字符var s = "????"; s.charCodeAt(0) // 55362 s.charCodeAt(1) // 57271 s.codePointAt(0) // 134071 //codePointAt 方法在第一个字符上,正确地识别了“????”,返回了它的十进制码点 134071(即十六进制的20BB7)
-
转化为16进制
let s = '????a'; s.codePointAt(0).toString(16) // "20bb7" s.codePointAt(2).toString(16) // "61"
-
codePointAt()
方法的参数,仍然是不正确的。比如,上面代码中,字符a
在字符串s
的正确位置序号应该是 1,但是必须向codePointAt()
方法传入 2-
解决这个问题的一个办法是使用
for...of
循环,因为它会正确识别 32 位的 UTF-16 字符let s = '????a'; for (let ch of s) { console.log(ch.codePointAt(0).toString(16)); } // 20bb7 // 61
-
另一种方法也可以,使用扩展运算符(
...
)进行展开运算let arr = [...'????a']; // arr.length === 2 arr.forEach( ch => console.log(ch.codePointAt(0).toString(16)) ); // 20bb7 // 61
-
String.raw()
-
ES6 还为原生的 String 对象,提供了一个
raw()
方法。该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法String.raw`Hi\n${2+3}!` // 实际返回 "Hi\\n5!",显示的是转义后的结果 "Hi\n5!" String.raw`Hi\u000A!`; // 实际返回 "Hi\\u000A!",显示的是转义后的结果 "Hi\u000A!" String.raw`Hi\n${2+3}!` // 实际返回 "Hi\\n5!",显示的是转义后的结果 "Hi\n5!" String.raw`Hi\u000A!`; // 实际返回 "Hi\\u000A!",显示的是转义后的结果 "Hi\u000A!"
-
String.raw()
本质上是一个正常的函数,只是专用于模板字符串的标签函数。如果写成正常函数的形式,它的第一个参数,应该是一个具有raw
属性的对象,且raw
属性的值应该是一个数组,对应模板字符串解析后的值// `foo${1 + 2}bar` // 等同于 String.raw({ raw: ['foo', 'bar'] }, 1 + 2) // "foo3bar"
实例方法:includes(),startsWith(),endsWith()
-
includes():返回布尔值,表示是否找到了参数字符串
-
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部
-
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部
let s = 'Hello world!'; s.startsWith('Hello') // true s.endsWith('!') // true s.includes('o') // true
-
这三个方法都支持第二个参数,表示开始搜索的位置
let s = 'Hello world!'; s.startsWith('world', 6) // true s.endsWith('Hello', 5) // true s.includes('Hello', 6) // false
实例方法:repeat()
-
repeat
方法返回一个新字符串,表示将原字符串重复n
次'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(0) // ""
-
参数如果是小数,会被取整;但是,如果参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。0 到-1 之间的小数,取整以后等于
-0
,repeat
视同为 0'na'.repeat(2.9) // "nana" 'na'.repeat(-0.9) // ""
-
如果
repeat
的参数是负数或者Infinity
,会报错'na'.repeat(Infinity) // RangeError 'na'.repeat(-1) // RangeError
-
参数
NaN
等同于 0'na'.repeat(NaN) // ""
-
如果
repeat
的参数是字符串,则会先转换成数字'na'.repeat('na') // "" 'na'.repeat('3') // "nanana"
实例方法:padStart(),padEnd()
-
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。
padStart()
用于头部补全,padEnd()
用于尾部补全 。padStart()
和padEnd()
一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'
-
如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串
'xxx'.padStart(2, 'ab') // 'xxx' 'xxx'.padEnd(2, 'ab') // 'xxx'
-
如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串
'abc'.padStart(10, '0123456789') // '0123456abc'
-
如果省略第二个参数,默认使用空格补全长度
'x'.padStart(4) // ' x' 'x'.padEnd(4) // 'x '
实例方法:trimStart(),trimEnd()
-
trimStart()
消除字符串头部的空格,trimEnd()
消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串const s = ' abc '; s.trim() // "abc" s.trimStart() // "abc " s.trimEnd() // " abc"
-
浏览器还部署了额外的两个方法,
trimLeft()
是trimStart()
的别名,trimRight()
是trimEnd()
的别名
实例方法:replaceAll()
-
字符串的实例方法
replace()
只能替换第一个匹配,如果要替换所有的匹配,不得不使用正则表达式的g
修饰符'aabbcc'.replace('b', '_') // 'aa_bcc''aabbcc'.replace(/b/g, '_') // 'aa__cc'
-
ES2021 引入了
replaceAll()
方法,可以一次性替换所有匹配'aabbcc'.replaceAll('b', '_') // 'aa__cc'
-
如果
searchValue
是一个不带有g
修饰符的正则表达式,replaceAll()
会报错。这一点跟replace()
不同'aabbcc'.replace(/b/, '_') // 不报错'aabbcc'.replaceAll(/b/, '_') // 报错
-
replaceAll()
的第二个参数是一个字符串,表示替换的文本,其中可以使用一些特殊字符串-
$&
:匹配的子字符串。 -
$
`:匹配结果前面的文本。 -
$'
:匹配结果后面的文本。 -
$n
:匹配成功的第n
组内容,n
是从1开始的自然数。这个参数生效的前提是,第一个参数必须是正则表达式。 -
$$
:指代美元符号$
// $& 表示匹配的字符串,即`b`本身 // 所以返回结果与原字符串一致 'abbc'.replaceAll('b', '$&') // 'abbc' // $` 表示匹配结果之前的字符串 // 对于第一个`b`,$` 指代`a` // 对于第二个`b`,$` 指代`ab` 'abbc'.replaceAll('b', '$`') // 'aaabc' // $' 表示匹配结果之后的字符串 // 对于第一个`b`,$' 指代`bc` // 对于第二个`b`,$' 指代`c` 'abbc'.replaceAll('b', `$'`) // 'abccc' // $1 表示正则表达式的第一个组匹配,指代`ab` // $2 表示正则表达式的第二个组匹配,指代`bc` 'abbc'.replaceAll(/(ab)(bc)/g, '$2$1') // 'bcab' // $$ 指代 $ 'abc'.replaceAll('b', '$$') // 'a$c'
-
-
replaceAll()
的第二个参数除了为字符串,也可以是一个函数,该函数的返回值将替换掉第一个参数匹配的文本'aabbcc'.replaceAll('b', () => '_') // 'aa__cc'
上一篇: es6 数组的扩展