关于javascript中RegExp的实例方法exex()和test()的小'冲突'

之前使用js中正则表达式的过程中,基本都是用的test方法,exec很少用,更别说test和exec混用的情况,今天碰巧遇到了这个情况,于是就发现了一个小'bug'。

比如我们要匹配全文中长度为4的单词,我们通常会这么做:

var str = 'my last name is junhua'
var reg = /w{4}/gvar result,
    i = 1
while (i > 0) {
    result = reg.exec(str)
    if(!result) {
        break;
    }
    console.log(result)
}

打印的结果为last和name,这就是我们想要的结果,但是如果我们在此之前调用过一次test了,会怎么样呢?

var str = 'my last name is junhua'
var reg = /w{4}/g
console.log(reg.test(str))
var result,
    i = 1
while (i > 0) {
    result = reg.exec(str)
    if(!result) {
        break;
    }
    console.log(result)
}

此时的打印结果就只有name了,那么我们的last去哪里了?我们先来思考一下test的作用是什么,就是判断我们的字符串与正则是否匹配,那么当遇到last时,我们的结果已经是true,就是匹配了,此时我们在代码中打印reg.lastIndex的值,值为7,这里解释下lastIndex值吧,lastIndex是一个整数,表示开始搜索下一个匹配项的字符位置,从0算起。看到这里是不是恍然大悟了,再进行下次匹配的时候,我们的查找是从7这个位置开始的,所以自然没有last只有name了,那么我们搞定这个小'bug'也就很简单了。

var str = 'my last name is junhua'
var reg = /w{4}/g
console.log(reg.test(str))
reg.lastIndex = 0;
var result,
    i = 1
while (i > 0) {
    result = reg.exec(str)
    if(!result) {
        break;
    }
    console.log(result)
}

把reg的lastIndex值设置初始值0即可。

虽然exec和test是两个方法,但是他们执行的过程中似乎都会动RegExp的实例属性lastIndex,这个是需要注意到的。