引子
检测一批手机号码是否都符合要求的格局,循环用正则校验,发现有效。去查找了下材料,发现了之前没有留神到中央。
- Origin
- My GitHub
问题
上面是问题重现:
const arr=['18311112222','18344445555','2857898098']
const reg = /^1[3-9]\d{9}$/g;
const result = arr.find(ele => !reg.test(ele));
console.info({result});
// {result: "18344445555"}
依照下面的正则,第二个号码符合要求,却返回了 false
,去查了材料,发现:
如果正则表达式设置了全局标记
g
,test()
的执行会扭转正则表达式lastIndex
属性。间断的执行test()
办法,后续的执行将会从lastIndex
处开始匹配字符串。
验证一下:
const arr=['18311112222','18344445555','2857898098']
const reg = /^1[3-9]\d{9}$/g;
const result = arr.find(ele => {
const lastIndex = reg.lastIndex;
console.info({lastIndex});
return !reg.test(ele);
});
// {lastIndex: 0}
// {lastIndex: 11}
解决办法
办法 1
去掉全局标记 g
,再想一想这个场景下没有必要应用全局匹配。
办法 2
应用 String.prototype.search()。
const arr=['18311112222','18344445555','2857898098']
const reg = /^1[3-9]\d{9}$/g;
const result = arr.find(ele => ele.search(reg) === -1);
办法 3
每次循环匹配的时候,从新申明一个正则。
const arr=['18311112222','18344445555','2857898098']
const result = arr.find(ele => {const reg = /^1[3-9]\d{9}$/g;
return !reg.test(ele);
});
参考资料
- MDN Regular Expressions
- MDN RegExp.prototype.test()
- 正则表达式