票务监控 的一个应用:高亮原页面关注城市名,原来做法为对每条记录的innerhtml都进行
var reg=/郑州/g; el.innerHTML=el.innerHTML.replace(reg,"....");
想优化一下,避免不必要的DOM操作,同时共享一个正则实例:
var reg=/郑州/g; if(reg.test(el.innerHTML)) el.innerHTML=el.innerHTML.replace(reg,"....");
结果出现了意想不到的结果,抽象如下:
例子:
猜猜下面代码内容:
var reg=/a/g;
console.log(reg.test('a'));
//console.log(reg.lastIndex);
console.log(reg.test('a'));
//console.log(reg.lastIndex);
吃惊的话看看下面:
var reg=/a/g;
console.log(reg.test('a'));
//console.log(reg.lastIndex);
console.log(reg.test('ba'));
//console.log(reg.lastIndex);
还是要看规范:
15.10.6.3 RegExp.prototype.test(string)
The following steps are taken:
1. Let match be the result of evaluating the RegExp.prototype.exec (15.10.6.3) algorithm upon this
RegExp object using string as the argument.
2. If match is not null, then return true; else return false.
我一直忽略了原来 test 实际上是 :
(r.exec(s) != null)
那么知道exec 对待 g 正则表达式,会记录 lastIndex 到这个正则表达式上,这样子的话 第二个 test 则会从第一个 test 的 lastIndex 开始匹配,出现了上述的结果。
总结原因:
1.test 等于 调用exec
2.lastIndex 存在于正则表达式中,而不是 java 一样有一个 matcher 对象存放 index,或者像 perl 一样 lastIndex 实际上和字符串关联,而javascript 这样子lastIndex和正则表达式关联,test还是最好不要设 g。
3.不成熟的优化等于魔鬼,实际上我可以再单独设一个检测正则表示式即可:
var reg=/郑州/g; var reg2=/郑州/; if(reg2.test(el.innerHTML)) el.innerHTML=el.innerHTML.replace(reg,"....");
PS:共享带来的问题:
有时想为了一点内存,共享几个对象实例,而对于正则表达式则要特别小心,因为正则实例的一些状态比如lastIndex在不同的操作中(test,exec)常常会被影响的,例如:
var script_re = /x/g;
var m,x = "avbxz",loop = 1;
while (m = script_re.exec(x)) {
console.log(script_re.lastIndex + " : " + m[0]);
//重置lastIndex要死循环喽
//"y".replace(script_re, "");
//console.log("after replace : "+script_re.lastIndex );
//"y".match(script_re);
//console.log("after match : "+script_re.lastIndex );
loop++;
if (loop == 100) {
alert("die!");
break;
}
}
updated : 2010-12-10
用 match 取代 test
最好还是不要用 test 来进行判断 :
var reg=/d/g;
console.log(reg.test("dd"));
console.log(reg.test("dg"));
因为 test 在 //g 会导致lastIndex 记载在该正则表达式中影响后续操作,如果不在乎性能的话,可用 match 取代:
var reg=/d/g;
console.log("dd".match(reg));
console.log("dg".match(reg));
本文探讨了正则表达式在JavaScript中的使用技巧及注意事项,特别是如何避免因全局搜索导致的状态遗留问题。
1064

被折叠的 条评论
为什么被折叠?



