我的代码类似于对象数组中的过滤条目:
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行),它会变得一致,我得到我想要的结果。
你能看出这个逻辑有什么问题,并告诉我为什么它并不总能产生预期的东西?
答案 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()时一切正常。