当test()被调用两次时,为什么“g”修饰符会给出不同的结果?

时间:2012-01-18 14:11:28

标签: javascript regex

鉴于此代码:

var reg = /a/g;
console.log(reg.test("a"));
console.log(reg.test("a"));

我得到了这个结果:

true
false

我不知道这是怎么发生的。我已经在Node.js(v8)和Firefox浏览器中进行了测试。

2 个答案:

答案 0 :(得分:24)

要解决此问题,您可以删除g标记或重置lastIndex,如

var reg = /a/g;
console.log(reg.test("a"));
reg.lastIndex = 0;
console.log(reg.test("a"));

问题出现是因为test基于exec,它在第一个之后查找更多匹配项,如果传递相同的字符串并且存在g标记。

  

15.10.6.3 RegExp.prototype.test(string)#ⓉⓇ

     

采取以下步骤:

     
      
  1. 匹配是使用 string 作为参数在此RegExp.prototype.exec对象上评估RegExp(15.10.6.2)算法的结果。
  2.   
  3. 如果匹配不是null,则返回true;否则返回false
  4.   

exec的关键部分是15.10.6.2的第6步:

  

6。让global成为使用参数“global”调用R的[[Get]]内部方法的结果   7.如果global为false,则让i = 0。

i未重置为0时,exec(因此test)不会开始查看字符串的开头。

这对exec很有用,因为你可以循环来处理每个匹配:

 var myRegex = /o/g;
 var myString = "fooo";
 for (var match; match = myRegex.exec(myString);) {
   alert(match + " at " + myRegex.lastIndex);
 }

但显然它对test没那么有用。

答案 1 :(得分:2)

通常选择一个测试来检查某些模式是否匹配,但是全局标志允许您遍历字符串以计算匹配,或者像exec一样,对每个lastIndex执行某些操作。另一个用途是在执行测试之前自己设置rx的lastIndex,以在某些字符索引之前忽略匹配。

var count=0, rx=/\s+/g, rx.lastIndex=100;
while(rx.test(string))count++;