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 属性,下次调用从上次结束位置继续搜,而不是重头开始。
例如:
立即学习“Java免费学习笔记(深入)”;
const r = /a/g;
console.log(r.test('abca')); // true
console.log(r.test('abca')); // true(从索引 2 开始,匹配到第 3 个 a)
console.log(r.test('abca')); // false(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确保全串替换 - 捕获分组提取内容:
'2023-04-01'.match(/(\d{4})-(\d{2})-(\d{2})/)返回数组,[0]是完整匹配,[1]、[2]、[3]是各括号内容
真正难的不是写出一个能跑的正则,而是理解它在不同方法(test/exec/match/replace)下的状态表现、边界行为和性能代价。尤其当模式变长、嵌套或含回溯时,lastIndex、标志组合、字符串长度三者一碰就容易出隐性 bug。










