摘自《ES6标准入门 第三版》
-
具名组匹配
有一个“具名匹配”的提案,其实允许为每一个组匹配指定一个名字,即便于阅读代码,又便于引用。
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('2019-08-16');
const year = matchObj.groups.year; // 2019
const month = matchObj.groups.month; // 08
const day = matchObj.groups.day; // 16
上面的代码中,“具名组匹配”在圆括号内部,在模式的头部添加“问好 + 尖括号 + 组名”(?),然后就可以在 exec 方法返回结果的 groups 属性上引用该组名。同时,数字序号(matchObj[1])依然有效。 具名组匹配等于为每一组匹配加上了 ID,这样便于描述匹配的目的。如果组的顺序变了,也不用改变匹配后的处理代码。 如果具名组没有匹配,那么对应的 groups 对象属性会是 undefined。
const RE_OPT_A = /^(?<as>a+)?$/;
const matchObj = RE_OPT_A.exec('');
matchObj.groups.as // undefined
'as' in matchObj.groups // true
上面的代码中,具名组 as 没有找到匹配,那么matchObj.groups.as 属性值就是 undefined,并且 as 这个键名在 groups 是始终存在的。
-
解构赋值和替换
有了具名组匹配以后,可以使用解构赋值直接从匹配结果上为变量赋值。
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
one // foo
two // bar
字符串替换时,使用 $<组名> 引用具名组。
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u/;
'2019-08-16'.replace(re, '$<day>/$<month>/$<year>') // 16-08-2019
上面的代码中,replace 方法的第二个参数是一个字符串,而不是正则表达式。replace 方法的第二个参数也可以是函数,该函数的参数序列如下。
'2019-08-16'.replace(re, (
matched, // 整个匹配结果 2019-08-16
capture1, // 第一个组匹配 2019
capture2, // 第二个组匹配 08
capture3, // 第三个组匹配 16
position, // 匹配开始的位置 0
S, // 原字符串 2019-08-16
groups, // 具名组构成的一个对象 {year, month, day};
) => {
let {day, month, yaer} = args[args.length -1];
return `${day}/${month}/${year}`
});
具名组匹配在原来的基础上新增了最后一个函数参数:具名组构成的一个对象。函数内部可以直接对这个对象进行解构赋值。