bug背景
const reg = /CAM/gi reg.test("FCAM_B0") // true reg.test("FCAM_A0") // false
在 JavaScript 中,使用带有 g(全局)标志的正则表达式进行多次 test() 调用时会出现一个特殊行为,这可能会导致你观察到的现象。
问题分析
const reg = /CAM/gi;
reg.test("FCAM_B0"); // 返回 true
reg.test("FCAM_A0"); // 返回 false(但你可能期望 true)
原因解释
- 当你使用
g标志时,正则表达式对象会维护一个lastIndex属性,记录上次匹配的位置 - 第一次调用
test("FCAM_B0"):- 在 "FCAM_B0" 中找到 "CAM"(位置 1)
- 设置
lastIndex = 4(匹配结束的位置)
- 第二次调用
test("FCAM_A0"):- 从
lastIndex = 4开始搜索 - "FCAM_A0" 只有 7 个字符,从位置 4 开始找不到 "CAM"
- 返回 false 并重置
lastIndex = 0
- 从
解决方案
方法1:不使用全局标志(推荐)
const reg = /CAM/i; // 去掉 g 标志
reg.test("FCAM_B0"); // true
reg.test("FCAM_A0"); // true
方法2:每次测试前重置 lastIndex
const reg = /CAM/gi;
reg.test("FCAM_B0"); // true
reg.lastIndex = 0; // 重置搜索位置
reg.test("FCAM_A0"); // true
方法3:每次创建新的正则表达式
/CAM/gi.test("FCAM_B0"); // true
/CAM/gi.test("FCAM_A0"); // true
何时需要使用 g 标志
g 标志主要用于需要多次匹配的场景,如:
String.prototype.match()String.prototype.replace()- 循环中的多次匹配
对于简单的 test() 检查,通常不需要 g 标志。