同一正则表达式多次测试同一字符串返回交替结果的原因
正则表达式多次测试同一字符串返回交替结果的原因
问题场景
这是我的正则表达式实现示例:
const regexes = [/(.*)\.should\.(.*)/gi]; console.log(regexes.map((re) => re.test('This is .should. true'))); console.log(regexes.map((re) => re.test('This is .should. true'))); console.log(regexes.map((re) => re.test('This is .should. true'))); console.log(regexes.map((re) => re.test('This is .should. true')));
在开发者控制台运行后,返回结果是:
[true] [false] [true] [false]
但预期应该每次都返回[true],为什么会出现交替的true和false?
核心原因
问题出在正则表达式的g(全局匹配)标志上。当正则启用g标志时,正则对象会维护一个叫lastIndex的属性,专门记录下一次匹配的起始位置:
- 第一次调用
test(),从字符串开头(lastIndex=0)匹配,成功找到符合模式的内容,返回true,同时lastIndex被更新到本次匹配结束的位置(也就是整个字符串的末尾)。 - 第二次调用
test()时,会从lastIndex的位置开始匹配,此时已经到了字符串末尾,自然找不到匹配项,返回false,同时lastIndex被重置为0。 - 第三次调用又回到开头匹配,成功返回
true,lastIndex再次跳到末尾,如此循环就出现了交替结果。
解决办法
有两种简单的处理方式:
- 移除
g标志:如果你的需求只是判断字符串是否符合该模式,不需要全局多次提取匹配内容,直接删掉g标志,正则改为/(.*)\.should\.(.*)/i。这样每次test()都会从头开始匹配,每次都会返回true。 - 手动重置
lastIndex:如果必须保留g标志,每次调用test()前手动把lastIndex设为0即可:
console.log(regexes.map((re) => { re.lastIndex = 0; return re.test('This is .should. true'); }));
内容的提问来源于stack exchange,提问作者Habibillah
相关产品推荐
相关产品推荐

