正则表达式主要用于处理文本数据,即字符串。在ES6中,随着字符串操作的变更,正则表达式也进行了相应更新
构造函数
在ES5中,使用构造函数方式创建正则表达式的方式有两种
第一种情况是,参数一是一个字符串,这时第二个参数表示正则表达式的修饰符(flag)
var regexp = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
第二种情况是,参数是一个正则表示式,这时不能设置第二个参数,否则会报错
var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;
// 报错
var regex = new RegExp(/xyz/, 'i');
ES6改变了这种行为,可以使用第二个参数指定修饰符。而且,返回的正则表达式会忽略原有的正则表达式的修饰符,只使用新指定的修饰符
console.log(new RegExp(/abc/ig, 'i').flags);//i
flags属性
ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符
var p1 = /[bc]at/i;
// ES5的source属性返回正则表达式的正文
console.log(p1.source);//'[bc]at'
// ES6的flags属性返回正则表达式的修饰符
console.log(p1.flags);//'i'
正则方法
字符串对象有四个方法可以使用正则表达式: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]
u修饰符
ES6 对正则表达式添加了u修饰符,含义为“Unicode模式”,用来正确处理大于\uFFFF的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码
/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true
点号
元字符点号.
在正则表达式中,含义是匹配除回车符\r、换行符\n、行分割符\u2028和段分隔符\u2029外的任意单个字符,但是对于码位大于0xFFFF的 Unicode 字符,点字符不能识别,必须加上u修饰符
var text = "" ;
console.log(text.length); // 2
console.log(/^.$/u.test(text)); //true
console.log(/^.$/.test(text));//false
大括号
ES6 新增了使用大括号表示 Unicode 字符,这种表示法在正则表达式中必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词
/\u{20BB7}/u.test('') // true
/\u{61}/u.test('a') // true
/\u{61}/.test('a') // false
量词
使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的 Unicode 字符
/{2}/u.test('') // true
/{2}/.test('') // false
预定义模式
使用u修饰符后,预定义模式会正确识别码点大于0xFFFF的 Unicode 字符
/^[\s\S]$/u.test('') // true
/^[\s\S]$/.test('') // false
字符串长度
虽然ES6不支持字符串码位数量的检测,length属性仍然返回字符串编码单元的数量。但是利用[\s\S],再加上u修饰符,就可以正确检测字符串长度
function codePointLength(str) {
var ret = str.match(/[\s\S]/gu);
return ret ? ret.length : 0;
}
var str = '';
console.log(str.length); // 4
console.log(codePointLength(str)); // 2
unicode属性
ES6为正则实例对象新增unicode属性,表示是否设置了u修饰符
console.log(/^\uD83D/u.unicode); // true
console.log(/^\uD83D/.unicode); // false
检测支持
u修饰符是语法层面的变更,尝试在不兼容 ES6 的 JS 引擎中使用它会抛出语法错误。可以写一个函数检测当前引擎是否支持u修饰符
function hasRegExpU() {
try {
var pattern = new RegExp(".", "u");
return true;
} catch (ex) {
return false;
}
}
y修饰符
ES6 为正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符。这个修饰符与g修饰符类似,都表示全局匹配,不同之处在于下一次匹配的起始位置,g修饰符是从剩余字符的第一个匹配位置开始,而y修饰符是从剩余字符的第一个位置开始
var s = 'aaa_aa_a';
var p1 = /a+/y;
var p2 = /a+/g;
// 第一次匹配,都是从第一个a开始,所以结果相同
console.log(p1.exec(s)) // 'aaa'
console.log(p2.exec(s)) // 'aaa'
// 第二次匹配,一个从索引3开始,一个从索引4开始
console.log(p1.exec(s)) // null
console.log(p2.exec(s)) // 'aa'
注意: y修饰符只有在调用 exec()和test()这两个正则匹配方法时,才会进行全局匹配;如果调用match()、replace()等字符串的方法时,不会进行全局匹配
'a1a2a3'.match(/a\d/y) // ["a1"]
'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]
sticky属性
ES6为正则实例对象新增sticky属性,表示是否设置了u修饰符
console.log(/a+/y.sticky); // true
console.log(/a+/.sticky); // false
检测支持
function hasRegExpY() {
try {
var pattern = new RegExp(".", "y");
return true;
} catch (ex) {
return false;
}
}
逆序环视
关于环视和正序环视的介绍移步至此
一直以来,JavaScript 语言的正则表达式,只支持正序环视(又称先行断言),直到ES2018的出现,JS支持了逆序环视(又称后行断言)
正序环视分为肯定正序环视和否定正序环视。肯定正序环视的记法是(?=n),表示前面必须是n才匹配;否定正序环视的记法是(?!n),表示前面必须不是n才匹配
// a后面必须是b,才会执行匹配a
console.log(/a(?=b)/.exec('abc'));//['a']
console.log(/a(?=b)/.exec('ac'));//null
// a后面必须不是b,才会执行匹配a
console.log(/a(?!b)/.exec('abc'));//null
console.log(/a(?!b)/.exec('ac'));//['a']
// a后面必须是b,才会执行匹配ab
console.log(/a(?=b)b/.exec('abc'));//['ab']
逆序环视同样分为肯定逆序环视和否定逆序环视。肯定逆序环视的记法是(?<=n),表示后面必须是n才匹配;否定逆序环视的记法是(?<!n),表示后面必须不是n才匹配
// b前面必须是a,才会执行匹配b
console.log(/(?<=a)b/.exec('abc'));//['b']
console.log(/(?<=a)b/.exec('bc'));//null
// b前面必须不是a,才会执行匹配b
console.log(/(?<!a)b/.exec('abc'));//null
console.log(/(?<!a)b/.exec('bc'));//['b']
// b前面必须是a,才会执行匹配ab
console.log(/a(?<=a)b/.exec('abc'));//['ab']