javascript正则表达式中有趣的奇偶现象

翅膀的初衷

发表于2015-09-08 22:21:52

有个很多年前我带过的同事来问我一个JS正则问题,大概就是正则第一次匹配A参数时,可以正常匹配,第二次匹配本应该能正常匹配的参数B时,却匹配失败。

我多次检测正则的写法确认其完全无误后,于是乎忍不住开始感兴趣起来。代码简化如下:

var r = new RegExp("^0|1$", "ig")
console.log(r.test("0")) //true 匹配
console.log(r.test("1")) //false 不匹配

理论上,这二个表达式应该都能正常匹配,但是结果却出人意料。

在多次测试中,将二个表达式调换位置,有趣的现象出现了:

var r = new RegExp("^0|1$", "ig")
console.log(r.test("1")) //true 匹配
console.log(r.test("0")) //false 不匹配

从这里看得出,匹配的结果,竟然跟位置有关。再稍稍改变代码如下:

span style="color: #0000FF;">var r = new RegExp("^0|1$", "ig")
console.log(r.test("0")) //true 匹配
console.log(r.test("0")) //false 不匹配
console.log(r.test("0")) //true 匹配
console.log(r.test("0")) //false 不匹配
console.log(r.test("0")) //true 匹配
console.log(r.test("0")) //false 不匹配

只要是奇次均能匹配,偶次均无法匹配。而在测试中,去掉正则的全局匹配模式(g)则完全正常。

经过一番搜索,终于找到答案:

在JS的正则表达式中,全局匹配模式下,test每次匹配会变换游标,不会重新初化,而是会接着上次结束的位置开始。第一次test(0)前,游标位置是0,所以能 正则匹配表达式,第一次匹配结束后,第二次匹配结束,游标位置是1,故第二次匹配失败.第三次开始匹配时,游标又回到了0,第三次匹配成功,依此循环……

我们可以使用 r.lastIndex 查看游标位置,同样,我们在上述代码中,加上游位代码,可以看出问题所在:

var r = new RegExp("^0|1$", "ig") console.log(r.lastIndex) //0 console.log(r.test("0")) //true 匹配 console.log(r.lastIndex) //1 console.log(r.test("0")) //false 不匹配 console.log(r.lastIndex) //0 console.log(r.test("0")) //true 匹配 console.log(r.lastIndex) //1 console.log(r.test("0")) //false 不匹配 console.log(r.lastIndex) //0 console.log(r.test("0")) //true 匹配 console.log(r.lastIndex) //1 console.log(r.test("0")) //false 不匹配

结论:在JS正则表达式中,使用test时,切记不要使用全局模式。正确代码如下:

var r = new RegExp("^0|1$", "i")
console.log(r.test("0")) //true 匹配
console.log(r.test("0")) //true 匹配

原创作品,转载请注明 作者:翅膀的初衷 出处:www.jiniannet.com