ES6入门之正则的扩展

1. 正则的扩展

  1. 参数为字符串, 那么第二个参数表示正则表达式的修饰符,如下:
var regex = new RegExp('xyz', 'i')  
// 等价于
var regex = /xyz/i
  1. 参数为一个正则表达式,这时返回一个原有正则表达式的拷贝。如下:
var regex = new RegExp(/xyz/i)
// 等价于
var regex = /xyz/i
  1. Es6中改变了这种行文。如果RegExp构造函数第一个参数是正则对象,那第二个参数可以指定修饰符,并且返回的正则表达式会忽略原有正则表达式的修饰符,只使用新指定的修饰符。 如下:
new RegExp(/abc/ig, 'i').flags
// 原有的ig 被 i 覆盖

2. 字符串的正则方法

字符串对象共有4个方法,可以使用正则表达式: match()、 replace()、search() 和 split()。在Es6中 全部调用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

3. u 修饰符

ES6 对正则表达式添加了 u 修饰符,用来正确处理大于\uFFFF的Unicode字符。如下:

/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true
// 如上代码因为在ES5中 不支持四个字节的 UTF-16编码,会将为识别为两个字符 导致 第二行为true
但是加了 u 修饰符后,ES6将为识别为一个字符,所以第一行为flase

4. RegExp.prototype.unicode 属性

正则实例对象新增 unicode 属性,用来判断表示是否设置了u修饰符,如下:

const r1 = /hello/;
const r2 = /hello/u;

r1.unicode // false
r2.unicode // true

5. y 修饰符

和 g 修饰符相似,全局匹配,但是下次匹配都是从上次匹配成功的下一个位置开始。而g 只要剩余位置中存在匹配即可,y 必须从剩余的第一个位置开始。如下:

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]
r2.exec(s) // null

// 第一次执行后 为 _aa_a g 只要剩余位置存在即可匹配,返回 aa
// y 则是从上一次结果后的第一个位置开始,因为是_ 所以返回null

6. RegExp.prototype.sticky 属性

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

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

7. RegExp.prototype.flags 属性

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

// ES5 的 source 属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"

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

8. s 修饰符:dotAll 模式

匹配的是任意单个字符,用来匹配任意单个字符,如下:

/foo.bar/s.test('foo\nbar') // true

9. Unicode 属性类

ES2018 引入了一种新的类的写法\p{…}和\P{…},允许正则表达式匹配符合 Unicode 某种属性的所有字符。

const regexGreekSymbol = /\p{Script=Greek}/u;
regexGreekSymbol.test('π') // true

10. 具名组匹配

正常多个匹配 可能用圆括号包起,如下:

const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31

但是以上的写法不容易看懂,理解较为困难,而且只能用数字序号,另外如果数组顺序变了,还需要修改引用的序号。所以就有了具名组匹配。允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。即使组的顺序变了,叶不用去更改匹配后的处理代码。如下:

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31

// 格式: “具名组匹配”在圆括号内部,模式的头部添加“问号 + 尖括号 + 组名”(?<year>)

11. String.prototype.matchAll

如果一个正则表达式在一个字符串中有多个匹配,现在使用的是 g 修饰符 或者 y 修饰符 循环 取出。现在有了新的提案。就是用 String.prototype.matchAll 一次性取出,但是它返回的不是一个数组,而是一个遍历器。然后可以用 for … of 取出。