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

字符串中的字符有两种,一种是由一个编码单元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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354