【神奇的BUG】在使用正则表达式时,结果明明是 true,不走 if 却走 else,但是此时既不是 true也不是false,请看我如何狡辩

前言

在进行需求开发时,碰到了一个神奇的、莫名的Bug。

在项目中,我用到了正则表达式,出于职业操作,我先把它声明定义出来,没毛病吧。

然后继续,我要判断一下我的输入是否符合当前的正则规则。

此时,神奇的事情发生了。。。

我输入的内容正则表达式判断结果我 true,但是 if 的判断结果却是 false 走了 else

在这里插入图片描述
WHAT????

甚是疑惑,一度以为是我眼花了,那先上问题代码


代码

let value = "0";
const regExp = /\d/g;
// \d => 匹配一个数字字符,等价于[0-9]
// g  => 是全局匹配
console.log("判定", regExp.test(value));
if (regExp.test(value)) {console.log("进入了true")
} else {console.log("进入了false")
}

输出结果:

判定 true
进入了false

是不是很疑惑,上面的正则判断的结果明明是 true,可是为什么还会走 else 呢???

下面请听我给大家伙狡辩


听我狡辩

其实,你没错,他也没错,都是缘分惹的祸。。。

首先 const regExp = /\d/g; 声明的正则表达式 (g) 为全局匹配模式

简单来说,全局匹配模式就是对指定校验字符串的多次校验,每一次校验会改变它的 lastIndex 值,lastIndex 属性的初始值为 0,每次找到匹配的项后,lastIndex 的值就被重置为匹配内容的下一个字符在字符串中的位置索引,用来标识 下次执行匹配时开始查找的位置

如果找不到匹配的项 lastIndex 的值会被设置为 0。

看到这,有可能你很迷惑。那么来看一下下面的代码:

console.log("判定", regExp.test(value));

此时,为第一次校验,执行完该代码之后, lastIndex 值将从 0 变为 1。

if (regExp.test(value))

到这,为第二次校验,此时 lastIndex 已经变为 1 了。

什么?不信??那么我们打印一下看看结果就知道了。。。

let value = "0";
const regExp = /\d/g;
console.log("未校验前:", regExp.lastIndex);
console.log("判定", regExp.test(value));
console.log("第一次校验:",regExp.lastIndex);
if (regExp1.test(value)) {console.log("进入了true")
} else {console.log("进入了false")
}

结果:

未校验前: 0
判定 true
第一次校验: 1
进入了false

看,没有骗你吧。

那么,你还记得 lastIndex 的作用是什么吗?

lastIndex 用来标识 下次执行匹配时开始查找的位置,所以在下次执行 if 时当然校验不到了。

另一个怪异事件,此时的校验结果既不是 true 也不是 false

let value = "0";
const regExp = /\d/g;
console.log("判定", regExp.test(value));
if (regExp.test(value) === true) {console.log('true');
}else if(regExp.test(value) === false) {console.log('false');
}else {console.log('其它');
}

结果:

判定 true
其它

至于为什么会出现上面提到的既不是 true 也不是 false 的原因,这是因为: else if 中又做了一次校验,前文中也有提到,即:如果找不到匹配的项 lastIndex 的值会被设置为 0,所以校验值会在 truefalse 之间变化。


解决方案

上面狡辩的也差不多了,大家伙应该也都看明白到底是怎么回事啦,那么我再给出两个解决方案吧:

1. 不使用全局校验

这是最简单的方法了,把表达式校验改为:

const regExp = /\d/;

去掉全局匹配 (g) 就可以了。

如果不使用全局校验,那么,lastIndex 在每次的检验中都为 0。

2. 还想使用全局校验

如果还想使用全局校验,那就把

console.log("判定", regExp.test(value));

这行代码删掉就可以了。

3. 在不删除 console.log 打印前提下,还想使用全局校验

在它的下面重新设置 lastIndex = 0 即可。

let value = "0";
const regExp = /\d/g;
console.log("判定", regExp.test(value));
regEx.lastIndex = 0;
if (regExp1.test(value)) {console.log("进入了true")
} else {console.log("进入了false")
}

这样相当于将它的 lastIndex 重新设置为 0,不会影响后续操作。


总结

看了我有理有据的狡辩,是不是对这个问题彻底明白了。

如果这个文章对您有所帮助,欢迎一键三连哦~

各位,加油!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部