为什么我看到不一致的JavaScript逻辑行为循环与alert()与没有它?

时间:2008-10-16 18:35:50

标签: javascript regex

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

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检查,两个条件都是单独的,但有时整个表达式的计算结果为false)。但是,如果我实际上在这个if语句中调用alert()(如第4行),它会变得一致,我得到我想要的结果。

你能看出这个逻辑有什么问题,并告诉我为什么它并不总能产生预期的东西?

3 个答案:

答案 0 :(得分:38)

好的,我现在看到了。你的问题的关键是使用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);

上面的示例创建了一个非常简单的正则表达式的实例:它匹配“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()之前立即创建了正则表达式,并且从未多次调用test(),因此您将永远不会遇到意外行为... 除非您正在使用调试器,允许您在侧面添加另一个test()的呼叫。对。随着Firebug的运行,包含您对test()的调用的监视表达式将导致您的代码或监视结果中出现间歇性false结果,具体取决于首先获取的结果。让你慢慢疯了......

当然,没有g旗,livin'很容易:

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);

建议

  • 当您不需要时避免使用全局标记。
  • 请注意您在调试器中评估的内容:如果存在副作用,则会影响程序的行为。

答案 1 :(得分:0)

我无法想象有两种JavaScript表达式单独评估为true的情况,但组合时则不然。

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

在说出event[0].show时,您是否引用了正确的索引,您的意思是event[i].show吗?

答案 2 :(得分:0)

这似乎是你在事件数组中遇到某种竞争条件,这就是为什么当你使用alert()时一切正常。