Javascript 正则需要注意的问题

Javascript 正则需要注意的问题

·

1 min read

Table of contents

前情提要

时隔多年,又被这个问题坑了一次,事情是这样的,我在一个需求里使用 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。

解决

主要有两种办法吧:

  1. 如果没需求,就不要使用 global 描述符

  2. 不要将正则赋值给变量,直接使用字面量去调用 exec 等函数(/^[A-L](上|下|左|右)$/g.exec('A上')),这样每次调用都会创建新的 Regex 对象,lastIndex 也不会被保留下来

  3. 如果做不到上面两点,记得在调用 exec 后手动将 lastIndex 重置