工作踩坑之JS的正则/g特性

27 阅读2分钟

在工作中碰到了一个之前一直没注意,但是碰到了真要命的坑。

这次坑出现的环境是在一个普通的输入密码的情景:使用公司自己的UI配合上自己写的正则进行校验,来判断用户输入两次密码是否一致,并且是否包含特殊符号。

因为有多处使用,为了日后维护,通过声明一个正则,很轻松的就能实现。但是一个小小的/g却给我留下了莫名其妙的bug。

在代码中,我先声明了一个正则。

var a = /[%?&+"' ]/g

在后续的代码中可以直接这样调用即可实现特殊符号的校验。

a.test(password)

但是奇怪的事情却发生了,假如用户输入了两次一模一样的密码admin123%,第二次输入的密码会出现校验通过的情况,开始明明正则里已经包含了特殊符号!

后面查阅了正则的相关特性才偶然发现,罪魁祸首竟然是小小的/g

带有 /g 的正则表达式会带有一个属性lastIndex,该属性存放一个整数,它声明的是上一次匹配文本之后的第一个字符的位置,上次匹配的结果是由方法RegExp.exec()RegExp.test()找到的,它们都以Iastindex属性所指的位置作为下次检索的起始点。这样,就可以通过反复调用这两个方法来遍历一个字符串中的所有匹配文本。该属性是可读可写的。只要目标字符串的下一次搜索开始,就可以对它进行设置。当方法exec()test()再也找不不到可以匹配的文本时,它们会自动把 lastlndex属性重置为0。

image.png

简而言之,就是:是他会忽略已经匹配到的文本,从上一次匹配到的位置开始向后匹配。

img_v2_6af6b070-49e2-4e46-91b6-7620fd7979fg.jpg

因此,会出现正则校验密码是否包含特殊符号时,校验通过的情况。最后修订也十分简单,直接删去g即可,判断密码是否包含特殊符号无需/g进行多次匹配,有包含特殊符号就不通过。

就是这个一个小小的让人忽视的特性带来了奇奇怪怪的bug,JS真是深奥啊?!