为什么我看到使用alert()与不使用alert的JavaScript逻辑行为循环不一致

Why am I seeing inconsistent JavaScript logic behavior looping with an alert() vs. without it?

本文关键字:alert JavaScript 不一致 循环 我看 为什么      更新时间:2023-09-26

我有类似于在对象数组中过滤条目的代码:

var filterRegex = new RegExp(".*blah.*","ig");
if (filterRegex.test(events[i].thing) && events[i].show) {
    console.log("SUCCESS: filtering thing " + i + " " + events[i].thing);
    events[i].show = false;
    numevents--;
}

我得到了与此if条件不一致的结果(使用Firebug进行检查,两个条件分别为true,但有时整个表达式的计算结果为false)。然而,如果我真的把一个调用的alert()放在这个if语句中(如第4行),它就会变得一致,并且我得到了我想要的结果。

你能看出这个逻辑有什么错误吗?告诉我为什么它不总是产生预期的结果?

好的,我现在看到了。问题的关键是使用g(全局匹配)标志:当为正则表达式指定此标志时,它将被设置为可以执行多次,每次都从上次停止的地方开始。它在lastIndex属性中保留了一个"书签":

var testRegex = /blah/ig;
// logs: true 4
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
// logs: true 9 
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
// logs: false 0
console.log(testRegex.test("blah blah"), testRegex.lastIndex);

上面的例子创建了一个非常简单的regex的实例:它匹配字符串中任何地方的大写或小写"blah",并且可以多次匹配(g标志)。在第一次运行时,它匹配第一个"blah",并将lastIndex设置为4(第一个"blah"之后的空间索引)。第二次运行从lastIndex开始匹配,匹配第二个blah,并将lastIndex设置为9,使其超过数组末尾。第三次运行不匹配-lastIndex是伪造的-并将lastIndex设置为0。因此,第四次运行将产生与第一次相同的结果。

现在,你的表达式比我的要贪婪得多:它会匹配"blah"之前或之后的任何数量的任何字符。因此,无论对哪个字符串进行测试,如果它包含"blah",它将始终与整个字符串匹配,并将lastIndex设置为刚刚测试的字符串的长度。这意味着,如果你两次调用test(),第二次测试总是会失败:

var filterRegex = /.*blah.*/ig;
// logs: true, 9
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
// logs: false, 0 
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);

幸运的是,由于您在调用test()之前立即创建了regex,并且从未多次调用test(),因此您永远不会遇到意外行为除非您正在使用一个调试器,该调试器允许您在侧面添加对test()的另一个调用。是的。在运行Firebug的情况下,包含对test()的调用的监视表达式将导致间歇性的false结果显示在代码中或监视结果中,具体取决于哪一个先到达它。让你慢慢发疯。。。

当然,没有g标志,生活很容易:

var filterRegex = /.*blah.*/i;
// logs: true, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
// logs: true, 0 
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);

建议

  • 当你不需要全局标志时,避免使用它
  • 在调试器中评估时要小心:如果有副作用,它可能会影响程序的行为

我无法想象在任何情况下,两个JavaScript表达式单独计算为true,但在组合时不计算为true。

你确定这两个表达式每次都会产生一个布尔值吗?(好吧,让regex.test()不产生布尔值是很困难的,但event.show呢。这有时可能是未定义的吗?

你说event[0].show时指的是正确的索引吗?你不是说event[i].show吗?

这似乎是事件数组面临某种竞争条件的原因,这就是为什么当您使用alert()时,一切都很好。