JavaScript正则表达式由RegExp构造函数和字面量语法支持,字面量复用实例而构造函数每次新建;test()在g标志下因lastIndex状态导致“跳着匹配”,需重置或改用match()。
JavaScript 正则表达式是内置的模式匹配引擎,不是字符串方法,也不是第三方库——它由 RegExp 构造函数和字面量语法(/pattern/flags)共同支撑,直接集成在语言运行时中。
两种方式等价,但行为细节有差异:
/\d{3}-\d{4}/ —— 每次出现都复用同一个实例,适合静态、固定模式;多次调用 .test() 时若带 g 标志,会因内部 lastIndex 状态导致结果不一致new RegExp('\\d{3}-\\d{4}', 'g') —— 每次执行都新建实例,适合动态拼接模式(比如用户输入的关键词),注意反斜杠要双写(字符串转义一次,正则再转义一次)test() 在全局模式下会“跳着匹配”这是 RegExp.prototype.test() 和 g 标志配合时最常踩的坑:它会修改正则对象的 lastIndex 属性,下次调用从上次结束位置继续搜,而不是重头开始。
例如:
const r = /a/g;
console.log(r.test('abca')); // true
console.log(r.test('abca')); // true(从索引 2 开始,匹配到第 3 个 a)
console.log(r.test('abca')); // fal
se(lastIndex 已超长度)解决办法:
- 不需要全局匹配时,去掉 g
- 必须用 g 且反复测试同一字符串,每次调用前手动重置:r.lastIndex = 0
- 改用 String.prototype.match(),它不改变正则状态,返回数组或 null
实际开发中高频需求,直接对应到具体方法和标志:
/^[^\s@]+@[^\s@]+\.[^\s@]+$/,用 .test() 即可,不需要 g
str.match(/\d+/g) —— g 不可少,否则只返回第一个匹配项及其额外信息(index、input 等)str.replace(/hello/gi, 'hi'),i 处理大小写,g 确保全串替换'2025-04-01'.match(/(\d{4})-(\d{2})-(\d{2})/) 返回数组,[0] 是完整匹配,[1]、[2]、[3] 是各括号内容真正难的不是写出一个能跑的正则,而是理解它在不同方法(test/exec/match/replace)下的状态表现、边界行为和性能代价。尤其当模式变长、嵌套或含回溯时,lastIndex、标志组合、字符串长度三者一碰就容易出隐性 bug。