ES6中正则表达式的一些变更


ES6学习系列


粘滞正则表达式

y修饰符在ES6标准化后正式成为正则表达式的一个专有扩展。它会影响正则表达式搜索过程中的sticky属性,当在字符串中开始字符匹配时,它会通知搜索从正则表达式的lastIndex属性开始进行,如果在指定位置没能成功匹配,则停止继续匹配

以下有普通的正则表达式(pattern ),全局匹配的正则表达式(globalPattern )和粘滞效果的正则表达式(stickyPattern )。普通正则表达式的lastIndex不会随着操作而改变,而全部匹配和粘滞匹配的lastIndex属性都会随着不断匹配而移动。随着lastIndex的移动,第二次匹配时全局匹配和粘滞匹配的结果都变为了hello2,而且lastIndex的值也变为了14,而普通正则则都没有变化。

let text = "hello1 hello2 hello3",
   pattern = /hello\d\s?/,
   result = pattern.exec(text),
   globalPattern = /hello\d\s?/g,
   globalResult = globalPattern.exec(text),
   stickyPattern = /hello\d\s?/y,
   stickyResult = stickyPattern.exec(text);

// hello1 
console.log(result[0]);
// hello1
console.log(globalResult[0]);
// hello1
console.log(stickyResult[0]);

/**
 * 当执行操作时,g和y修饰符会把上次匹配后面一个字符的索引保存到lastIndex中;如果该操作匹配的结果为空,则lastIndex会被重置为0
 */
// 0
console.log(pattern.lastIndex);
// 7
console.log(globalPattern.lastIndex);
// 7
console.log(stickyPattern.lastIndex);

result = pattern.exec(text);
globalResult = globalPattern.exec(text);
stickyResult = stickyPattern.exec(text);

// hello1 
console.log(result[0]);
// hello2
console.log(globalResult[0]);
// hello2
console.log(stickyResult[0]);

// 0
console.log(pattern.lastIndex);
// 14
console.log(globalPattern.lastIndex);
// 14
console.log(stickyPattern.lastIndex);

另外,lastIndex的值可以自由进行设置,在设置之后,匹配将从被设置的位置开始进行。
接着上面的案例,将lastIndex都修改为1,对于普通正则表达式的匹配结果,没有任何影响。而全局匹配则从位置1开始查找,匹配了hello2 而不是hello1 。而粘滞匹配则没有任何匹配(从位置1开始不能匹配任何结果),并且将lastIndex设置为0。

pattern.lastIndex = 1;
globalPattern.lastIndex = 1;
stickyPattern.lastIndex = 1;


result = pattern.exec(text);
globalResult = globalPattern.exec(text);
// y修饰符会影响正则表达式搜索过程中的sticky属性,当在字符串中开始字符匹配时,它会通知搜索从正则表达式的lastIndex属性开始进行,如果在指定位置没有成功匹配,则停止继续匹配
stickyResult = stickyPattern.exec(text);

// 1
console.log(pattern.lastIndex);
// 14
console.log(globalPattern.lastIndex);
// 0
// 没有匹配 则lastIndex被重置为0
console.log(stickyPattern.lastIndex);

// hello1
// 没有修饰符的表达式自动忽略lastIndex的变化
console.log(result[0]);
// hello2 
// 使用了g修饰符的表达式,从第二个字符e开始搜索,继续向后匹配
console.log(globalResult[0]);
// index.js:25 Uncaught TypeError: Cannot read properties of null (reading '0')
// 此处修改了lastIndex为1,但是从位置1不能匹配正则表达式
try {
   console.log(stickyResult[0]);
} catch (error) {
   console.log(error);
}

可以通过以下函数来检测JavaScript引擎是否支持粘滞通配符

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

正则表达式的复制

在ES5当中,可以通过RegExp构造函数传递正则表达式作为参数来负责这个正则表达式,比如

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

此处的re2只是变量re1的一份拷贝,但如果给RegExp构造函数传递第二个参数,为正则表达式指定一个修饰符,则代码无法运行。如下所示

var re1 = /ab/i,
   re2 = new RegExp(re1),
   // 如果在ES5中执行会报错,当第一个参数为正则表达式时不可以使用第二个参数
   re3 = new RegExp(re1, "g");

如果在ES5环境中执行这段代码会抛出一个错误:当第一个参数为正则表达式时不可以使用第二个参数。ES6中修改了这个行为,即使第一个参数为正则表达式,也可以通过第二个参数修改其修饰符。比如

// /ab/i
console.log(re1.toString());
// /ab/i
console.log(re2.toString());
// /ab/g
console.log(re3.toString());

// true
console.log(re2.test("ab"));
// true
console.log(re3.test("ab"));

// true
console.log(re2.test("AB"));
// false  由于使用了g修饰符替代了i 所以大小写就敏感了
console.log(re3.test("AB"));

flags属性

为了配合新加入的修饰符,ES6还新增了与之相关的新属性。在ES5当中,可以通过source属性获取正则表达式的文本,但如果要获取使用的修饰符,则只能通过截取字符串的方式进行。如下代码所示

function getFlags(re) {
    var text = re.toString();
    // 这段代码会将正则表达式转换为字符串并识别最后一个/后面的字符,以此来确定使用了哪些修饰符
    return text.substring(text.lastIndexOf("/") + 1, text.length);
}
// source = ab,flags = i
console.log("source = " + re2.source + ",flags = " + getFlags(re2))
// source = ab,flags = g
console.log("source = " + re3.source + ",flags = " + getFlags(re3))

在ES6当中没有必要这么麻烦了,在ES6中新增了一个flags属性,它与source属性都是只读的原型属性访问器,对其值定义了getter方法,这极大了简化了调试和编写继承代码的复杂度。在ES6中比较新的版本中,访问flags属性会返回所有应用于当前正则表达式的修饰符字符串。比如

/** 
 * 为了获取修饰符更方便,在ES6中新增了一个flags属性,访问flags属性会返回
 * 所有应用于当前正则表达式的修饰符字符串
 * 结合source属性和flags属性可以免去格式化正则表达式之忧
 */
// source = ab,flags = i
console.log("source = " + re2.source + ",flags = " + re2.flags);
// source = ab,flags = g
console.log("source = " + re3.source + ",flags = " + re3.flags);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lang20150928

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值