资讯专栏INFORMATION COLUMN

深入理解ES6之《字符串及正则》

liaosilzu2007 / 1471人阅读

摘要:字符串中的字符有两种,一种是由一个编码单元位表示的字符,另一种是由两个编码单元位表示的辅助平面字符在中,所有字符串的操作都是基于位编码单元接受编码单元的位置而非字符位置作为参数,返回与字符串中给定位置对应的码位,即一个整数值也就是说对于字符

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

codePointAt

codePointAt 接受编码单元的位置而非字符位置作为参数,返回与字符串中给定位置对应的码位,即一个整数值
也就是说对于BMP字符集中的字符,codePointAt方法的返回值与charCodeAt方法的相同,而对于非BMP字符集来说返回值则不同

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

检测字符占用编码单元数量

function is32Bit(c) {
  return c.codePointAt(0)>0xFFFF
}
console.log(is32Bit("?"))//true
console.log(is32Bit("a"))//false
String.fromCodePoint

codePoint方法在字符串中检索一个字符的码位,也可以使用String.fromCodePoint方法根据指定的码位生成一个字符

可以将String.fromCodePoint看成更完整版本的String.fromCharCode,因为对于BMP中的所有字符,这俩方法执行结果相同,只有传递非BMP的码位作用参数时,二者执行结果才有可能不同

normalize

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

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

或者上述代码也可以这样

let values = ["test", "demo", "compare", "sort"]
values.sort(function (first, second) {
  // let firstNormalized = first.normalize(),
  //   secondNormalized = second.normalize();  //可以写成这种形式也可以写成如下这种形式
  let firstNormalized = first.normalize("NFC"),
  secondNormalized = second.normalize("NFC");
  if (firstNormalized < secondNormalized) return -1
  else if (firstNormalized === secondNormalized) return 0
  else return 1
})

Unicode标准化形式有如下几种

正则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(/[sS]/gu)
  return result ? result.length : 0
}
console.log(codePointLength("abc"))//3
console.log(codePointLength("?ab"))//3
console.log("?ab".length)//4

检测引擎是否支持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--字符串的位置是12减去8之后还余下4
console.log(msg.includes("o", 8))//false--从字符串world中的r开始匹配

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

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

console.log("X".repeat(5))//XXXXX
正则表达式y修饰符

在字符串开始字符匹配时,它会通知搜索从正则表达式的lastIndex属性开始进行,如果在指定位置未能成功匹配则停止继续匹配

let text = "hello1 hello2 hello3",
  pattern = /hellods?/,
  result = pattern.exec(text),
  globalPattern = /hellods?/g,
  glogbalResult = globalPattern.exec(text),
  stickyPattern = /hellods?/y,
  stickyResult = stickyPattern.exec(text);

console.log(result[0])//hello1
console.log(glogbalResult[0])//hello1
console.log(stickyResult[0])//hello1
pattern.lastIndex = 1
globalPattern.lastIndex = 1
stickyPattern.lastIndex = 1
result = pattern.exec(text)
glogbalResult = globalPattern.exec(text)
stickyResult = stickyPattern.exec(text)
console.log(result[0])//hello1
console.log(glogbalResult[0])//hello2
console.log(stickyResult[0])//报错

关于修饰符有2点:
1、只有调用exec和test方法才会涉及lastIndex
2、当lastIndex的值为0时,如果正则表达式中含有^则是否使用粘滞正则表达式并无差别,如果lastIndex的值不为0则该表达式永远不会匹配到正确结果

let pattern=/hellod/y
console.log(pattern.sticky)//true
正则表达式复制

ES5中复制正则表达式只能这样

var re1 = /ab/i,
  re2 = new RegExp(re1);

如果想要对re1重新指定修饰符则不行,ES6 增加了这一新功能

var re1 = /ab/i,
  re2 = new RegExp(re1, "g")
console.log(re1)//   /ab/i
console.log(re2)//   /ab/g
console.log(re1.test("ab"))//true
console.log(re2.test("ab"))//true
console.log(re1.test("AB"))//true
console.log(re2.test("AB"))//false
正则中的flags属性
let re=/ab/g
console.log(re.source)// ab
console.log(re.flags)// g   --ES新增的属性
模板字面量

在ES6之前多行字符串只能在一个新行最前方添加反斜杠来承接上一行代码

var message="Multiline
string"

但是这样有一个问题,在控制台输出在了同一行,所以只能通过手工插入n换行符

ES6中通过反撇号来创建多行字符串,在反撇号中所有空白符都属于字符串的一部分,所以千万要小心缩进

字符串占位符可以包含任意的JS表达式,占位符中可访问作用域中所有可访问的变量,尝试嵌入一个未定义的变量总是会抛出错误

let count = 10,
  price = 2.5,
  message = `${count} items cost $ ${(count * price).toFixed(2)}.`
  //10 items cost $ 25.00.

字符串占位符还可以内嵌,内嵌的{后必须包含在反撇号中

let name = "angela",
  message = `Hello,${`
    my name is ${name}`
  }`
console.log(message)

String.raw访问字符串前的原生字符串

let msg1 = `Multiline
stirng`,
  msg2 = String.raw`Multiline
string`
console.log(msg1)//Multiline
//string
console.log(msg2)//Multiline
string

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87367.html

相关文章

  • H5学习

    摘要:为此决定自研一个富文本编辑器。本文,主要介绍如何实现富文本编辑器,和解决一些不同浏览器和设备之间的。 对ES6Generator函数的理解 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。 JavaScript 设计模式 ② 巧用工厂模式和创建者模式 我为什么把他们两个放在一起讲?我觉得这两个设计模式有相似之处,有时候会一个设计模式不能满...

    aristark 评论0 收藏0
  • 前端文档收集

    摘要:系列种优化页面加载速度的方法随笔分类中个最重要的技术点常用整理网页性能管理详解离线缓存简介系列编写高性能有趣的原生数组函数数据访问性能优化方案实现的大排序算法一怪对象常用方法函数收集数组的操作面向对象和原型继承中关键词的优雅解释浅谈系列 H5系列 10种优化页面加载速度的方法 随笔分类 - HTML5 HTML5中40个最重要的技术点 常用meta整理 网页性能管理详解 HTML5 ...

    jsbintask 评论0 收藏0

发表评论

0条评论

liaosilzu2007

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<