建议42:用好正则表达式静态值
正则表达式的静态属性比较特殊,有两个名字:长名(全称)和短名(简称,以美元符号开头表示),详细说明见表2.1。
表2.1 RegExp的静态属性
长名 短名 说明
input $_ 最后用于匹配的字符串,即传递给exec()或test()方法的字符串
lastMatch $& 最后匹配的字符
lastParen $+ 最后匹配的分组
leftContext $` 在上次匹配之前的子字符串
multiline $* 用于指定是否所有表达式都使用多行模式的布尔值
rightContext $' 在上次匹配之后的子字符串
在下面的这个示例中借助正则表达式的静态属性,匹配字符串“Javascript”,不区分大小写:
var s = "Javascript,not Javascript";
var r = /(Java)Script/gi;
var a = r.exec(s);
alert(RegExp.input); //"Javascript,not Javascript"
alert(RegExp.leftContext); //空字符串,因为在第一次匹配操作时,左侧没有内容
alert(RegExp.rightContext); //",not Javascript"
alert(RegExp.lastMatch); //"Javascript "
alert(RegExp.lastParen); //"Java"
上面示例演示了正则表达式的几个静态属性的用法。
input属性实际上存储的是被执行匹配的字符串,即整个字符串“Javascript,not Javascript”。
leftContext属性存储的是执行第一次匹配之前的子字符串,这里为空,因为在第一次匹配时文本“Javascript”左侧为空,而rightContext属性存储的是执行第一次匹配之后的子字符串,即为“,not Javascript”。
lastMatch属性包含的是第一次匹配的子字符串,即为“Javascript”。
lastParen属性包含的是第一次匹配的分组,即为“Java”。如果模式中包含多个分组,则会显示最后一个分组所匹配的字符。例如:
var r = /(Java)(Script)/gi;
var a = r.exec(s); //执行匹配操作
alert(RegExp.lastParen); //返回"Script",而不再是"Java"
也可以使用短名来读取这些属性所包含的值,考虑到这些短名不符合JavaScript语法规范,因此必须使用中括号运算符来进行读取操作。不过对于$_属性来说,由于它符合JavaScript标识符语法规范,因此可以直接使用。例如,针对上面示例也可以这样设计:
var s = "Javascript,not Javascript";
var r = /(Java)(Script)/gi;
var a = r.exec(s);
alert(RegExp.$_); //"Javascript,not Javascript"
alert(RegExp["$`"]); //空字符串
alert(RegExp["$'"]); //",not Javascript"
alert(RegExp["$&"]); //"Javascript "
alert(RegExp["$+"]); //"Java"
这些属性的值都是动态的,每次执行exec()或test()方法时,所有属性值都会被重新设置。当在下面示例中执行第一次匹配和第二次匹配时,这些静态属性值都会实时动态更新。
var s = "Javascript,not Javascript";
var r = /Scrip(t)/gi; // 第一次定义的匹配模式
var a = r.exec(s); // 执行第一次匹配
alert(RegExp.$_); //"Javascript,not Javascript"
alert(RegExp["$`"]); //"Java"
alert(RegExp["$'"]); //",not Javascript"
alert(RegExp["$&"]); //"Script"
alert(RegExp["$+"]); //"t"
var r = /Jav(a)/gi; // 第二次定义的匹配模式
var a = r.exec(s); // 执行第二次匹配
alert(RegExp.$_); //"Javascript,not Javascript"
alert(RegExp["$`"]); //空字符串
alert(RegExp["$'"]); //"Script,not Javascript"
alert(RegExp["$&"]); //"Java"
alert(RegExp["$+"]); //"a"
通过上面的示例可以看出,RegExp对象的静态属性是公共的,对于所有正则表达式来说是可以共享的,因此这些静态属性的值也是实时变化的。
multiline属性与上面几个属性不同,它不会根据每次执行的操作进行实时更新,并且还可以控制所有正则表达式的m标志项。例如:
var s = "anbnc";
var r = /w+$/g; // 定义匹配模式
var a = s.match(r); // 执行默认匹配,返回数组["c"]
RegExp.multiline = true; // 动态设置模式为多行匹配
var a = s.match(r); //["a", "b", "c"]
提示:IE和Opera浏览器不支持RegExp.multiline属性,考虑到浏览器的兼容性,不建议读者使用这种动态方式设置正则表达式的多行匹配模式。