引子

检测一批手机号码是否都符合要求的格局,循环用正则校验,发现有效。去查找了下材料,发现了之前没有留神到中央。

  • 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 ,去查了材料,发现:

如果正则表达式设置了全局标记 gtest() 的执行会扭转正则表达式 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()
  • 正则表达式