ES6正则表达式扩展笔记


Posted in Javascript onJuly 25, 2017

 前面的话

正则表达式是javascript操作字符串的一个重要组成部分,但在以往的版本中并未有太多改变。然而,在ES6中,随着字符串操作的变更, ES6也对正则表达式进行了一些更新。本文将详细介绍ES6正则表达式扩展

构造函数

在 ES5 中,RegExp构造函数的参数有两种情况。

第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)

var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;

第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝

var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;

但是,ES5 不允许此时使用第二个参数添加修饰符,否则会报错

// Uncaught TypeError: Cannot supply flags when constructing one RegExp from another
var regex = new RegExp(/xyz/, 'i');

ES6 改变了这种行为。如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且,返回的正则表达式会忽略原有的正则表达式的修饰符,只使用新指定的修饰符

console.log(new RegExp(/abc/ig, 'i').flags);//i

上面代码中,原有正则对象的修饰符是ig,它会被第二个参数i覆盖

【flags】

ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符

//ES5的source属性返回正则表达式的正文
/abc/ig.source//"abc"
// ES6的flags属性返回正则表达式的修饰符
/abc/ig.flags//'gi'

正则方法

字符串对象共有4个方法,可以使用正则表达式:match()、replace()、search()和split()

ES6 将这4个方法,在语言内部全部调用RegExp的实例方法,从而做到所有与正则相关的方法,全都定义在RegExp对象上

String.prototype.match 调用 RegExp.prototype[Symbol.match]
String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
String.prototype.search 调用 RegExp.prototype[Symbol.search]
String.prototype.split 调用 RegExp.prototype[Symbol.split]

u修饰符

正则表达式可以完成简单的字符串操作,但默认将字符串中的每一个字符按照16位编码处理。为了解决这个问题, ES6 对正则表达式添加了u修饰符,含义为“Unicode模式”,用来正确处理大于\uFFFF的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码

/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true

一旦为正则表达式设置了 u 修饰符,正则表达式将会识别32位的辅助平面字符为1个字符,而不是两个

【点号】

点(.)字符在正则表达式中,含义是除了换行符以外的任意单个字符。对于码位大于0xFFFF的 Unicode 字符,点字符不能识别,必须加上u修饰符

var text = "?" ;
console.log(text.length); // 2
console.log(/^.$/.test(text));//false
console.log(/^.$/u.test(text)); //true

【大括号】

ES6 新增了使用大括号表示 Unicode 字符,这种表示法在正则表达式中必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词

/\u{61}/.test('a') // false
/\u{61}/u.test('a') // true
/\u{20BB7}/u.test('?') // true

【量词】

使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的 Unicode 字符

/a{2}/.test('aa') // true
/a{2}/u.test('aa') // true
/?{2}/.test('??') // false
/?{2}/u.test('??') // true

【预定义模式】

u修饰符也影响到预定义模式,能否正确识别码点大于0xFFFF的 Unicode 字符

/^\S$/.test('?') // false
/^\S$/u.test('?') // true

【字符串长度】

上面代码的\S是预定义模式,匹配所有不是空格的字符。只有加了u修饰符,它才能正确匹配码点大于0xFFFF的 Unicode 字符

虽然ES6不支持字符串码位数量的检测,length属性仍然返回字符串编码单元的数量。利用[\s\S],再加上u修饰符,就可以写出一个正确返回字符串长度的函数

function codePointLength(text) {
 var result = text.match(/[\s\S]/gu);
 return result ? result.length : 0;
}
var s = '??';
console.log(s.length); // 4
console.log(codePointLength(s)); // 2

【检测支持】

u修饰符是语法层面的变更,尝试在不兼容 ES6 的 JS 引擎中使用它会抛出语法错误。如果要检测当前引擎是否支持u修饰符,最安全的方式是通过以下函数来判断

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

这个函数使用了RegExp构造函数并传入字符串'u'作为参数,该语法即使在旧版 JS 引擎中也是有效的。但是,如果当前引擎不支持u修饰符则会抛出错误

y修饰符

除了u修饰符,ES6 还为正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符

y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义

【全局匹配】

y修饰符的设计本意,就是让头部匹配的标志^在全局匹配中都有效

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;
console.log(r1.exec(s)); // ["aaa"]
console.log(r2.exec(s)); // ["aaa"]
console.log(r1.exec(s)); // ["aa"]
console.log(r2.exec(s)); // null

上面代码有两个正则表达式,一个使用g修饰符,另一个使用y修饰符。这两个正则表达式各执行了两次,第一次执行的时候,两者行为相同,剩余字符串都是_aa_a。由于g修饰没有位置要求,所以第二次执行会返回结果,而y修饰符要求匹配必须从头部开始,所以返回null。

如果改一下正则表达式,保证每次都能头部匹配,y修饰符就会返回结果了

var s = 'aaa_aa_a';
var r = /a+_/y;
console.log(r.exec(s)); // ["aaa_"]
console.log(r.exec(s)); // ["aa_"]

上面代码每次匹配,都是从剩余字符串的头部开始

【非全局匹配】

单单一个y修饰符使用match方法,只能返回第一个匹配,必须与g修饰符联用,才能返回所有匹配

'a1a2a3'.match(/a\d/y) // ["a1"]
'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]

[注意]y修饰符只有在调用 exec()和test()这两个正则匹配方法时,才会进行全局匹配;如果调用match()、replace()等字符串的方法时,不会进行全局匹配

【stiky属性】

与y修饰符相匹配,ES6 的正则对象多了sticky属性,表示是否设置了y修饰符

var r = /hello\d/y;
r.sticky // true

【应用】

y修饰符的一个应用,是从字符串提取 token(词元),y修饰符确保了匹配之间不会有漏掉的字符

const TOKEN_Y = /\s*(\+|[0-9]+)\s*/y;
const TOKEN_G = /\s*(\+|[0-9]+)\s*/g;
tokenize(TOKEN_Y, '3 + 4')// [ '3', '+', '4' ]
tokenize(TOKEN_G, '3 + 4')// [ '3', '+', '4' ]
function tokenize(TOKEN_REGEX, str) {
 let result = [];
 let match;
 while (match = TOKEN_REGEX.exec(str)) {
  result.push(match[1]);
 }
 return result;
}

上面代码中,如果字符串里面没有非法字符,y修饰符与g修饰符的提取结果是一样的。但是,一旦出现非法字符,两者的行为就不一样了

tokenize(TOKEN_Y, '3x + 4')
// [ '3' ]
tokenize(TOKEN_G, '3x + 4')
// [ '3', '+', '4' ]

上面代码中,g修饰符会忽略非法字符,而y修饰符不会,这样就很容易发现错误

【检测支持】

y修饰符与u修饰符类似,它也是一个语法层面的变更,尝试在不兼容 ES6 的 JS 引擎中使用它会抛出语法错误。如果要检测当前引擎是否支持y修饰符,可以通过以下函数来检测

function hasRegExpY() {
  try {
    var pattern = new RegExp(".", "y");
    return true;
  } catch (ex) {
    return false;
  }
}

这个函数使用了RegExp构造函数并传入字符串'y'作为参数,该语法即使在旧版 JS 引擎中也是有效的。但是,如果当前引擎不支持y修饰符则会抛出错误

总结

以上所述是小编给大家介绍的ES6正则表达式扩展笔记,希望对大家有所帮助,如果大家有任何疑问请给我留

言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript中的一些定位属性[图解]
Jul 14 Javascript
js获取图片大小的函数代码
Sep 20 Javascript
JS绘制生成花瓣效果的方法
Aug 05 Javascript
JS+DIV+CSS实现仿表单下拉列表效果
Aug 18 Javascript
简单解析JavaScript中的__proto__属性
May 10 Javascript
Bootstrap前端开发案例二
Jun 17 Javascript
红黑树的插入详解及Javascript实现方法示例
Mar 26 Javascript
Vue.js 实现数据展示全部和收起功能
Sep 05 Javascript
jquery分页优化操作实例分析
Aug 23 jQuery
Element Cascader 级联选择器的使用示例
Jul 27 Javascript
小程序实现上传视频功能
Aug 18 Javascript
vue 使用 v-model 双向绑定父子组件的值遇见的问题及解决方案
Mar 01 Vue.js
简单实现js拖拽效果
Jul 25 #Javascript
Vue实现一个返回顶部backToTop组件
Jul 25 #Javascript
基于jquery实现多级菜单效果
Jul 25 #jQuery
关于TypeScript中import JSON的正确姿势详解
Jul 25 #Javascript
微信JSSDK调用微信扫一扫功能的方法
Jul 25 #Javascript
利用node.js爬取指定排名网站的JS引用库详解
Jul 25 #Javascript
详解angularjs获取元素以及angular.element()用法
Jul 25 #Javascript
You might like
PHP7.0版本备注
2015/07/23 PHP
PHP7实现和CryptoJS的AES加密方式互通示例【AES-128-ECB加密】
2019/06/08 PHP
使用jquery插件实现图片延迟加载技术详细说明
2011/03/12 Javascript
js中判断数字\字母\中文的正则表达式 (实例)
2012/06/29 Javascript
JS获取URL中参数值(QueryString)的4种方法分享
2014/04/12 Javascript
探析浏览器执行JavaScript脚本加载与代码执行顺序
2016/01/12 Javascript
Bootstrap学习笔记之css组件(3)
2016/06/07 Javascript
JavaScript实现刷新不重记的倒计时
2016/08/10 Javascript
浅谈vant组件Picker 选择器选单选问题
2020/11/04 Javascript
全网小程序接口请求封装实例代码
2020/11/06 Javascript
[47:26]完美世界DOTA2联赛 LBZS vs Forest 第二场 11.07
2020/11/09 DOTA
python装饰器使用方法实例
2013/11/21 Python
python中使用xlrd、xlwt操作excel表格详解
2015/01/29 Python
基于python的Tkinter编写登陆注册界面
2017/06/30 Python
Python3处理HTTP请求的实例
2018/05/10 Python
对Python 3.2 迭代器的next函数实例讲解
2018/10/18 Python
pycharm 实现显示project 选项卡的方法
2019/01/17 Python
python正则表达式匹配不包含某几个字符的字符串方法
2019/07/23 Python
详解python中的模块及包导入
2019/08/30 Python
Python网络编程之使用TCP方式传输文件操作示例
2019/11/01 Python
Python用5行代码实现批量抠图的示例代码
2020/04/14 Python
Python日志处理模块logging用法解析
2020/05/19 Python
python学习将数据写入文件并保存方法
2020/06/07 Python
keras的siamese(孪生网络)实现案例
2020/06/12 Python
Python爬虫中Selenium实现文件上传
2020/12/04 Python
高级技校毕业生自荐信
2013/11/18 职场文书
清洁工岗位职责
2014/01/29 职场文书
成立公司计划书
2014/05/07 职场文书
应届毕业生求职信
2014/05/26 职场文书
人事专员岗位职责说明书
2014/07/30 职场文书
小学生感恩老师演讲稿
2014/08/28 职场文书
作弊检讨书范文
2015/05/06 职场文书
2016高中社会实践心得体会范文
2016/01/14 职场文书
《平移和旋转》教学反思
2016/02/19 职场文书
Oracle更换为MySQL遇到的问题及解决
2021/05/21 Oracle
MYSQL中文乱码问题的解决方案
2022/06/14 MySQL