有个需求需要匹配上传文件格式,我就写了一个正则来匹配,结果,发生了我做开发以来,不是亲眼所见都不会相信的bug!
下面我把代码简单的写一下:
const acceptReg = /.(jpg|jpeg|png|gif|bmp)$/gi;
const originFileObj = files[i];// 这个是获取的文件详情
const matched = originFileObj.name.match(/\.[\w]{2,6}$/);
console.log("第一次")
console.log(matched.length > 0 && acceptReg.test(matched[0])); // true
console.log(matched.length > 0); // true
console.log(acceptReg.test(matched[0])); // true
console.log("第二次")
console.log(matched.length > 0 && acceptReg.test(matched[0])); // false
console.log(matched.length > 0); // true
console.log(acceptReg.test(matched[0])); // true
console.log("第三次")
console.log(matched.length > 0 && acceptReg.test(matched[0])); // true
console.log(matched.length > 0); // true
console.log(acceptReg.test(matched[0])); // false
执行了上传一个文件,三次分别打印出不同结果,最奇怪的是 true && false 结果还为true了,一开始还以为是运算符的优先级的问题,结果改了优先级还是不行。
经过一顿断点调试,嗯。。。。发现了一些东西,正则里有个lastIndex属性一直在变。
好吧,然后查啊查,原来在js中每个正则表达式都是一个对象,这个对象有一个特别的实例属性lastIndex,表示的是下一次搜索开始的位置。
对于test()方法,在全局模式下,它每次执行都只会返回一个匹配项,并且会改变lastIndex的值,再次执行的时候,会从lastIndex这个位置开始继续搜索。但是对于非全局模式,test每次都只会返回第一个匹配的信息,lastIndex也不会变化。
找到原因之后,删掉全局模式,ok!!!以后千万别滥用全局模式了。正则虽好,但是还是有坑!