Javascript 正则需要注意的问题
前情提要
时隔多年,又被这个问题坑了一次,事情是这样的,我在一个需求里使用 exec
来验证用户的输入,像这样:
const text = /* 用户输入 */
const regex = /^[A-L](上|下|左|右)$/g
const match = regex.exec(text)
// 后续根据 match 是否为 null 判断匹配情况
结果呢,用户第一次输入“A上”,没有问题,第二次输入“H左”,没匹配上。
问题
关键在于正则的 global 描述符,也就是最后的 g
,如果不使用 global,那么会在匹配到一次后就退出了,而使用了 global 则可以匹配多次。
当我们使用 exec
的时候,如果匹配到了,他会让 regex 变量的 lastIndex
定位到匹配结果的末尾,比如说:
const regex = /^[A-L](上|下|左|右)$/g
// 此时 lastIndex 是 0
regex.exec('A上') // ['A上', '上', index: 0, input: 'A上', groups: undefined]
// 此时 lastIndex 是 2
regex.exec('A上') // null
// 此时 lastIndex 是 0
此时匹配的是“A上”,长度为 2,lastIndex
变成 2,下一次调用 exec
会从 2 再开始匹配。
那么再一次调用,匹配不到结果,所以返回 null
,这里 exec
会将 lastIndex
重置为 0。
解决
主要有两种办法吧:
如果没需求,就不要使用 global 描述符
不要将正则赋值给变量,直接使用字面量去调用
exec
等函数(/^[A-L](上|下|左|右)$/g.exec('A上')
),这样每次调用都会创建新的 Regex 对象,lastIndex
也不会被保留下来如果做不到上面两点,记得在调用
exec
后手动将lastIndex
重置