Javascript RegExp 的有趣测试

IT技术 javascript regex
2021-03-02 05:35:15

我写了一个 Javascript RegExp 测试来检测日期字符串格式,我错误地添加了一个多余的“g”标志并发现了一些有趣的东西。

var s = "2009/03/10";
var regex=/^\d{4}[/]\d{2}[/]\d{2}$/g;
alert(regex.test(s));
alert(regex.test(s));
alert(regex.test(s));
alert(regex.test(s));

我得到了一个“真”,然后是一个“假”,然后是另一个“真”,然后是另一个“假”。

如果我使用循环来执行它,我发现了一些更有趣的东西,我在 IE 和 Safari 中得到了四个“true”,在 FF、Chrome 中得到了 true、false、true、false。

for (var i=0; i<4; i++)
{
  var s = "2009/03/10";
  var regex=/^\d{4}[/]\d{2}[/]\d{2}$/g;
  alert(regex.test(s));
}

有没有人想解释为什么 Javascript 正则表达式的行为如此,以及是什么导致浏览器返回不同的结果?(与变量声明和生命范围有关?)

2个回答

当您在 JS RegExp 上使用全局标志时,“test”和“exec”方法都会在第一个匹配处停止,但会保留一个指向它们在字符串中停止搜索的位置的指针。可以在lastIndex属性上检查该指针当您再次调用“test”或“exec”时,它会开始搜索从lastIndex.

因此,当您在匹配整个字符串的字符串上测试 RegExp 时,lastIndex 设置为字符串的末尾。下次测试时,它从字符串的末尾开始,返回false,然后设置lastIndex回零。

MDC对这种行为有一个很好的解释

非常感谢,MDC的解释很清楚。
2021-04-26 05:35:15
例如,如果这会导致循环中的问题,您似乎可以在每次测试之前设置 lastIndex = 0。
2021-05-05 05:35:15
+1 感谢您的帮助,在每次测试解决我的问题之前设置 reg.lastIndex=0。
2021-05-12 05:35:15

为避免这种奇怪的行为,请不要使用全局 (g) 标志。

这段代码应该输出:'True','True','True','True'

var s = "2009/03/10";
var regex=/^\d{4}[/]\d{2}[/]\d{2}$/i;
alert(regex.test(s));
alert(regex.test(s));
alert(regex.test(s));
alert(regex.test(s));

全局(g)平面设置属性 RegExp.lastIndex。所以每个 test() 将从最后一个停止的地方开始。

有关更多信息,请参阅有关RegExp.lastIndex 的文档

但是如果我想要g标志怎么办?例如,在String.replace(regex,replacement)函数中重用相同的正则表达式没有 'g' 它只替换第一次出现。
2021-04-21 05:35:15