正则表达式字面量

JavaScript中的正则表达式也是对象,可以通过两种方式创建它们:

  • 使用new RegExp()构造函数
  • 使用正则表达式字面量

下面的示例代码展示了创建用来匹配一个反斜杠(\)的正则表达式的两种方法:

  1. // 正则表达式字面量
  2. var re = /\\/gm;
  3. // 构造函数
  4. var re = new RegExp("\\\\", "gm");

显然正则表达式字面量写法的代码更短,而且不会让你觉得在用像类一样的构造函数的思想在写正则表达式,因此更推荐使用字面量写法。

另外,如果使用RegExp()构造函数写法,还需要考虑对引号和反斜杠进行转义,正如上段代码所示的那样,用了四个反斜杠来匹配一个反斜杠。这会增加正则表达式的长度,而且让它变得难于理解和维护。正则表达式入门不是件容易的事,所以不要放弃任何一个简化它们的机会,尽量使用字面量而不是通过构造函数来创建正则表达式。

正则表达式字面量语法

正则表达式字面量使用两个斜杠包裹,主体部分不包括两端的斜线。在第二个斜线之后可以指定模式匹配的修饰符,修饰符不需要用引号引起来,JavaScript中有三个修饰符:

  • g,全局匹配
  • m,多行匹配
  • i,忽略大小写的匹配

修饰符可以自由组合,而且与顺序无关:

  1. var re = /pattern/gmi;

使用正则表达式字面量可以让代码更加简洁高效,比如当调用String.prototype.replace()方法时,可以传入正则表达式参数:

  1. var no_letters = "abc123XYZ".replace(/[a-z]/gi, "");
  2. console.log(no_letters); // 123

有一种不得不使用new RegExp()的场景,就是正则表达式是不确定,只有等到运行时才能确定下来的情况。

正则表达式字面量和构造函数还有另一个区别,就是字面量只在解析时创建一次正则表达式对象(译注:多次解析同一个正则表达式,会产生相同的实例对象)。如果在循环体内反复使用相同的字面量创建对象,则会返回第一次创建的对象以及它的属性(比如lastIndex)。下面这个例子展示了两次返回相同的正则表达式的情形。

  1. function getRE() {
  2. var re = /[a-z]/;
  3. re.foo = "bar";
  4. return re;
  5. }
  6. var reg = getRE(),
  7. re2 = getRE();
  8. console.log(reg === re2); // true
  9. reg.foo = "baz";
  10. console.log(re2.foo); // "baz"

在ECMAScript5中这种情况有所改变,相同正则表达式字面量的每次计算都会创建新的实例对象,目前很多现代浏览器也对此做了纠正。

最后需要提一点,不带new调用RegExp()(作为普通的函数)和带new调用RegExp()是完全一样的。