js中正则表达式使用regex.test的情况下如果使用了全局模式就会出现测试结果每次不一样的诡异情况,搜索了下原来是lasteIndex的锅。

太长不读 TL;DR

js中的regex.test包含属性lastIndex, 仅在全局模式下使用。使用一次后当你下一次使用regex.test他会从lastIndex的位置中开始测试而不是文本的开始。因此在全局模式下多次使用regex.test会返回不同的结果。

神奇的现象

今天朋友写代码的时候遇到了一个问题,测试正则

1
2
3
let regex1 = /^[\u4e00-\u9fa5]{2,15}$/g
console.log(regex1.test("我我"))
// 返回 True

多次运行console.log(regex1.test("我我")),每次返回值都在true和false中交替。
1
2
3
4
5
6
7
8
console.log(regex1.test("我我"))
// 返回 False
console.log(regex1.test("我我"))
// 返回 True
console.log(regex1.test("我我"))
// 返回 False
console.log(regex1.test("我我"))
// 返回 True

感觉我还是不会正确的搜索方法,搜了很多后在才google中隐约找到这篇文章,具体见引用
简单来说,全局模式的搜索在regex.test下是一个依次进行的过程,每次搜索到一个结果返回,并且记住这次搜索的位置,下次则从上次搜索到的位置开始继续。
因此在上述正则表达式中,规定了^$开始与结束,在全局模式下,每次搜索都会导致下次搜索从上次搜索的结尾处继续,因此返回false。
因为没有搜到于是lastIndex置0,则下次搜索又从开始进行,于是又变为了true。

Reference

[1] Benjamin Johnson.using “regex.test” with the “global” flag[EB/OL].https://benjaminjohnson.me/blog/regex-test-side-effects,2020-07-23.