互联网技术 · 2024年2月17日

js正则test方法的bug探讨

其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西

下面的代码都是在chrome的F12下调试的,大家可以研究一下

先来看个东西吧。

var re = /d/;
console.log( re.test(“1”) );
console.log( re.test(“1”) );
console.log( re.test(“1”) );
console.log( re.test(“1”) );

全部是 true 没问题。。

浅谈js正则之test方法bug篇

再次修改:

console.log( /d/g.test(“1”) );
console.log( /d/g.test(“1”) );
console.log( /d/g.test(“1”) );
console.log( /d/g.test(“1”) );

浅谈js正则之test方法bug篇

全部是 true,这究竟是为什么呢?

这些结果相当有意思,当然高手自然知道为什么,如果你知道的话,下面其实可以跳过不用看了,全是水文而已。。

正则里有一个 lastIndex 的属性,是下一次匹配的开始位置。

var re = /d/g;
console.log( re.test(“1”), re.lastIndex );
console.log( re.test(“1”), re.lastIndex );
console.log( re.test(“1”), re.lastIndex );
console.log( re.test(“1”), re.lastIndex );

浅谈js正则之test方法bug篇

可以看到 第一次匹配结果为 true 表示匹配成功,此时 lastIndex 记录下一次匹配的起始位置为 1。

于是第二次匹配的时候 从 “1” 字符串索引 1 的位置匹配,当然就匹配失败了,因为这个字符串只有一个字符,他的索引是 0。

而 /d/g.test(“1”) 这个为什么每次匹配成功能呢?

因为它直接用正则字面量,相当于每次重新创建一个正则对象,lastIndex 属性的初始值是 0。

所以每次都能匹配成功。

现在是不是理解了,包括 exec 也一样,每次匹配一个,lastIndex 记录下次匹配的起始位置。

如果非要用一个正则对象的,那就只有每次 test 前重置 lastIndex 了,这样才能保证他不出意外。

var re = /d/g;
console.log( re.test(“1”) );
re.lastIndex = 0;
console.log( re.test(“1”) );
re.lastIndex = 0;
console.log( re.test(“1”) );
re.lastIndex = 0;
console.log( re.test(“1”) );

浅谈js正则之test方法bug篇

好了,今天修改语法高亮插件花了不少时间,所以水了一篇,望大家海涵。。

OpenMagic API

Need more than content? Move into the product flow.

If you are here for model access, pricing, developer docs, or the future API console, the dedicated product path now lives on api.openmagic.ai.

登录免费注册