- 现象:两次执行结果不一致
const reg = /\s/g; //校验是否有空格
function regTestFun(str) {
console.log(reg.test(str));
}
regTestFun('12 34') // true
regTestFun('12 34') // false
-
原因:
- 使用带有全局标志的正则表达式进行匹配时,它会在字符串中查找所有的匹配项,并将当前匹配的结束位置保存在
lastIndex属性中。下一次使用同一个正则表达式对象进行匹配时,它会从lastIndex指定的位置开始搜索。 - 正则表达式
reg使用了全局标志g,会保留之前的匹配位置。连续多次调用regTestFun('12 34')方法时,每次调用中的reg.test(str)都会从上一次匹配结束的位置开始,而不是从字符串的开头。
- 使用带有全局标志的正则表达式进行匹配时,它会在字符串中查找所有的匹配项,并将当前匹配的结束位置保存在
-
解决
- 删除正则中的
/g(但是会出现只会匹配第一个,不满足需求)----不建议 - 在每次调用完
regTestFun后,重置reg.lastIndex = 0;(在实际项目中,往往会把正则写在一个专门的正则js文件中,而regTestFun调用一般在业务代码中,在业务代码中添加reg.lastIndex = 0;显然不合理)----不建议
- 删除正则中的
// 建议使用方式
// 全局正则汇总ts文件
function createRegex(pattern: RegExp | string, flag = ''): RegExp {
return new RegExp(pattern, flag);
}
export const reg = createRegex(/\s/g);
- 结论:
- 使用
test、match、replace都会出现这种情况 - 通过使用函数
createRegex封装正则表达式并在每次使用时动态创建新的正则表达式对象,可以避免全局标志 g 导致的结果不一致问题。 - 不使用全局标志
g:正则表达式在找到第一个匹配项后停止,并返回结果。下一次匹配将从上次匹配的结束位置开始。 - 使用全局标志
g:正则表达式会尝试在整个字符串中找到所有匹配项,并返回所有结果。下一次匹配将从上次匹配的结束位置继续,而不是从字符串的开头。
- 使用
// 使用`g`和不使用 `g`的代码示例
const str = "abcabcabc";
const regexWithoutG = /abc/;
const regexWithG = /abc/g;
console.log(str.match(regexWithoutG)); // 输出:["abc"]
console.log(str.match(regexWithG)); // 输出:["abc", "abc", "abc"]