参见英文答案 >
Why RegExp with global flag in Javascript give wrong results?4个
我有一个类似于对象数组中的过滤条目的代码:
我有一个类似于对象数组中的过滤条目的代码:
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--; }
如果条件(使用Firebug检查,两个条件都是单独的,但有时整个表达式的计算结果为false),我得到不一致的结果.然而,如果我真的把一个在这个if语句(如第4行)中调用的alert(),它变得一致,我得到了我想要的结果.
你可以看到这个逻辑有什么问题,告诉我为什么它不总是产生预期的?
解决方法
好的,我现在看.您的问题的关键是使用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”之后的空间的索引).第二次运行在最后一个Index开始匹配,匹配第二个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(),所以您永远不会遇到意外的行为…除非您使用调试器,否则可以添加另一个调用来测试()在一边.对.使用Firebug运行时,包含对test()的调用的监视表达式将导致在代码或监视结果中显示间歇性的错误结果,具体取决于首先获取到的结果.驾驶你慢慢疯狂
当然,没有g旗,livin很容易:
var filterRegex = /.*blah.*/i; // logs: true,0 console.log(filterRegex.test("blah blah"),filterRegex.lastIndex); // logs: true,filterRegex.lastIndex);
建议
>当您不需要时,避免使用全局标志.>小心你在调试器中的评估:如果有副作用,它会影响程序的行为.