为何正则test( )多次调用返回值却不同

前言:

一开始一个朋友发消息问我:

var a = ['123.JpG','123.jpg'];
var reg = /(jpg|png)$/ig;
a.forEach(v => {
    if(reg.test(v) === true){
        console.log(123)
    }
})

会输出什么。 我理所当然的说,当然是输出两个123了。

lastIndex:

QQ20181015090701.png

这时候你会发现,我们在连续使用一个正则匹配其他字符串的时候,第一次匹配是 true,而第二次匹配则是 false。

查看了一下 MDN文档 发现这样一个描述:

如果正则表达式设置了全局标志,test() 的执行会改变正则表达式 lastIndex属性。连续的执行test()方法,后续的执行将会从 lastIndex 处开始匹配字符串,(exec() 同样改变正则本身的 lastIndex属性值).

QQ20181015090907.png

解决方案:

  1. 方案1 既然文档说了是因为全局标志才会影响到lastIndex,于是可以把g去掉就可以了。
var reg = /(jpg|png)$/i;
console.log(reg.test(a[0])); //true
console.log(reg.test(a[0])); //true
  1. 方案2 有时候既然需要用到g,那就不能用到方案1的方法了。 其实,我们的lastIndex属性是可读可写的。 我们可以在下一次匹配的之前更改lastIndex的值来达到目的:
var reg = /(jpg|png)$/ig;
console.log(reg.test(a[0])); //true
console.log(reg.lastIndex); //7
reg.lastIndex = 0;
console.log(reg.test(a[0])); //true

最后:

再来回顾最开始的问题,我们只需要选择方案1或者方案2中的一个方法,即可实现输出两个123:

3.png

参考地址:

Comments