字符串和正则表达式(上)

字符串中的字符有两种,一种是由一个编码单元16位表示的BMP(Basic Multilingual Plane)字符,另一种是由两个编码单元32位表示的辅助平面字符。
在ES5中,所有字符串的操作都是基于16位编码单元。

codePointAt()方法

ES6中新增加里完全支持UTF-16的codePointAt()方法.

codePointAt接受编码单元的位置而非字符位置作为参数,返回与字符串中给定位置对应的码位,即一个整数值。

let txt='𠮷a'
console.log(txt.charCodeAt(0))//55362  --仅仅返回位置0处的第一个编码单元
console.log(txt.charCodeAt(1))//57271
console.log(txt.charCodeAt(2))//97

console.log(txt.codePointAt(0))//134071  --返回完整的码位,即使这个码位包含多个编码单元
console.log(txt.codePointAt(1))//57271
console.log(txt.codePointAt(2))//97

也就是说对于BMP字符集中的字符,codePointAt方法的返回值与charCodeAt方法的相同,而对于非BMP字符集来说返回值则不同。

  • charCodeAt()返回的只是位置0处的第一个编码单元。
  • codePointAt()返回完整的码为,即使这个码位包含多个编码单元。
    检测字符占用编码单元数量
function is32Bit(c) {
  return c.codePointAt(0)>0xFFFF
}
console.log(is32Bit('?'))//true
console.log(is32Bit('a'))//false

String.fromCodePoint()方法

  • codePointAt()方法是通过在字符串中检索一个字符的码位。
  • String.fromCodePoint()方法是根据制定的码位生成一个字符。
console.log(String.fromCodePoint(134071)) // 𠮷

normalize()方法

在对不同字符进行排序或比较时,会存在一种可能:它们是等效的。
1、规范的等效是指无论从哪个角度来看,两个序列的码位都是没有区别的
2、两个互相兼容的码位序列看起来不同,但是在特定情况下可以被交换使用
切记:在对比字符串前一定要把它们标准化为同一种形式

let values = ["test", "demo", "demo","compare", "sort"]
let normalized = values.map(function (txt) {
 return txt.normalize()
})
normalized.sort(function (first, second) {
if (first < second) console.log(-1)
else if (first === second) console.log(0)
else console.log(1)
})

上述代码也可以写成如下的格式:

let values = ["test", "demo", "compare", "sort"]
values.sort(function (first, second) {
 // let firstNormalized = first.normalize(),
 //     secondNormalized = second.normalize();  //可以写成这种形式也可以写成如下这种形式,默认NFC格式,也可以明确制定其他形式。
 let firstNormalized = first.normalize('NFC'),
 secondNormalized = second.normalize('NFC');
 if (firstNormalized < secondNormalized) return -1
 else if (firstNormalized === secondNormalized) return 0
 else return 1
})

Unicode标准化形式:

  • NFC(Normalization From Canonical),默认参数,表示“标准等价合成”,返回多个简单字符的合成字符。所谓“标准等价”指的是视觉和语义上的等价。
  • NFD(Normalization From Canonical Decompositon),表示“标准等价分解”,即在标准等价的前提下,返回合成字符分解的多个简单字符。
  • NFKC(Normalization From Compatibility Composition),表示“兼容等价合成”,返回合成字符。所谓“兼容等价”指的是语义上存在等价,但视觉上不等价,比如“囍”和“喜喜”。(此处用来举例,normalize ()方法不能识别中文。)
  • NFKD(Normalization From Compatibility Decompositon),表示“兼容等价分解”,即在兼容等价的前提下,返回合成字符分解的多个简单字符。

正则表达式u修饰符

当一个正则表达式使用u修饰符时,它就从编码单元操作切换为字符模式

u修饰符实例

let txt = '𠮷'
console.log(txt.length)//2
console.log(/^.$/.test(txt))//false
console.log(/^.$/u.test(txt))//true

正则表达式/^.$/匹配所有单字符字符串。

计算码位数量

function codePointLength(txt) {
 let result = txt.match(/[\s\S]/g)
 return result ? result.length : 0
}
function codePointLengthWithu(txt) {
 let result = txt.match(/[\s\S]/gu)
 return result ? result.length : 0
}
console.log(codePointLength('abc'))//3
console.log(codePointLength('𠮷ab'))//4
console.log(codePointLengthWithu('abc'))//3
console.log(codePointLengthWithu('𠮷ab'))//3
console.log('𠮷ab'.length)//4

调用match()方法检查空白和非空白字符,使用[\s\S]来确保这个模式能够匹配新行。

检测引擎是否支持u修饰符

function hasRegExpU(params) {
 try {
   var pattern = new RegExp(".", "u")
   return true
 } catch (ex) {
   return false
 }
}

如果你的代码仍然需要运行在老式的JS引擎中,使用修饰符时切记使用RegExp构造函数,这样可以避免发生语法错误,并且你可以有选择的检测和使用u修饰符而不会造成系统异常终止。

其他字符串变更

字符串中的子串识别

  • includes() 在字符串中检测是否包含指定文本
  • startsWith() 在字符串的起始部分是否包含指定文本
  • endsWith() 在字符串的结束部分是否包含指定文本
    以上三个方法都接受两个参数:1、要搜索的文本 2、(可选)开始搜索的索引值,如果指定的第二个参数则会比这个索引值的位置开始匹配,endsWith则从字符串长度减法这个索引值的位置开始匹配。
let msg = 'Hello world!'
console.log(msg.startsWith('Hello'))//true
console.log(msg.endsWith('!'))//true
console.log(msg.includes('o'))//true

console.log(msg.startsWith('o'))//false
console.log(msg.endsWith('world!'))//true
console.log(msg.includes('x'))//false

console.log(msg.startsWith('o', 4))//true--从字符串Hello中的‘o’开始
console.log(msg.endsWith('o', 8))//true--索引值为8的字符为‘r’,字符串减去‘r’及之后的字符串后开始匹配。
console.log(msg.includes('o', 8))//false--从字符串world中的r开始匹配

通过indexOf()和lastIndexof()寻找子串的位置,并且如果传一个正则表达式进去的话,它们会将传入的正则表达式转化为字符串并搜索它,而在includes()、startsWith()、endsWith()这三方法中,如果你不是传入字符串而是一个正则表达式则会报错。

repeat()方法

repeat()方法接受一个number类型的参数,表示该字符串的重复次数,返回当前字符串重复一定次数后的新字符串。

console.log('x'.repeat(3))//xxx
console.log('hello'.repeat(2))//hellohello
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。