写点什么

小心!正则 test() 匹配的一个“坑”

作者:掘金安东尼
  • 2022 年 7 月 20 日
  • 本文字数:1025 字

    阅读完需:约 3 分钟

小心!正则 test() 匹配的一个“坑”

本瓜相信你一定经常用以下这种最最简单的正则来判断字符串中是否存在某个子字符(别说了,我就是)🐶


const pattern = /ab/gpattern.test("abcd") // true
复制代码


这样去匹配,有什么问题吗?


不急,现在来让你猜一下,以下代码的输出?


const pattern = /ab/gconsole.log(pattern.test("abcd"))console.log(pattern.test("abcd"))console.log(pattern.test("abcd"))
复制代码


“不就是三个 true 吗?!”


在控制台上打印试试?惊不惊喜、意不意外?



为什么是 true 、false 、true ?


原来这里,这里有个小坑需要注意下,用 test() 连续做匹配的时候,会出错,是因为一个我们将要认识的 —— 正则类型 lastIndex 属性!


lastIndex 属性用于规定下次匹配的起始位置。


每次当我们用正则 RegExp.exec() 和 RegExp.test() 进行匹配的时候,如果返回为 true,lastIndex 属性的值会发生变化,会变成正确匹配的子字符串的最后位置,并将此位置作为下次检索的起始点。如果返回为 false,lastIndex 重置为 0 ;


所以,我们这样打印试试就知道了:


const pattern = /ab/gconsole.log(pattern.test("abcd")) // trueconsole.log(pattern.lastIndex) // 2console.log(pattern.test("abcd")) // falseconsole.log(pattern.lastIndex) // 0console.log(pattern.test("abcd")) // trueconsole.log(pattern.lastIndex) // 2
复制代码


当我们第一次调用 pattern.test("abcd")pattern.lastIndex 为 2, 即字母 b 的位置,当再次调用 pattern.test("abcd") 则会从 b 的位置往后搜索,搜不到 ab 了,返回 false ,同时 lastIndex 重置为 0 ,然后第三次调用 pattern.test("abcd") 又能正确返回 true 了,lastIndex 也变成了 2。


不知道这个坑,你踩到过没?



怎么解决呢?


方法一:手动清理 lastIndex


const pattern = /ab/gconsole.log(pattern.test("abcd")) // truepattern.lastIndex = 0console.log(pattern.test("abcd")) // true
复制代码


不过,这样手动清理很麻烦,显得很笨,所以建议用方法二。


方法二:用 match 来匹配


const pattern = /ab/gconsole.log("abcd".match(pattern)) // ['ab']console.log("abcdab".match(pattern)) // ['ab', 'ab']console.log("123".match(pattern)) // null
复制代码


match 是匹配的更优解,不用手动清理,存在则悉数返回成数组,不存在,返回 null



OK,以上便是本篇分享。点赞关注评论,为好文助力👍

我是掘金安东尼 🤠 100 万阅读量人气前端技术博主 💥 INFP 写作人格坚持 1000 日更文 ✍ 关注我,陪你一起度过漫长编程岁月 🌏

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2022.07.14 加入

社会我瓜哥,人狠话不多😎 微信 anthony1453,加我交个朋友😎 正联合【机械工业出版社】出版《程序员成长手册》,敬请期待😎 真正的大师,永远怀着一颗学徒的心(易)😎

评论

发布
暂无评论
小心!正则 test() 匹配的一个“坑”_正则_掘金安东尼_InfoQ写作社区