11

Basically, my question is about how Javascript handles regex literals.

Contrasting with number, string and boolean where literals are primitive data types and corresponding Number, String and Boolean objects exist with seamless type conversion, are regex literals anonymous instances of the RegExp object or is this a case of regex being treated like primitive data with seamless type conversion to RegExp?

"The complete Reference Javascript, 2nd edition, Powell and Schneider (MH)" contradicts itself - at one place the authors say that /regex/ is automatically typecasted into RegExp when needed and at another place they say that /regex/ is nothing but an instance of RegExp!

EDIT: Please provide a reference to a reliable source

KJ Saxena
  • 21,452
  • 24
  • 81
  • 109

3 Answers3

14

Here's what the spec has to say:

A regular expression literal is an input element that is converted to a RegExp object when it is scanned. The object is created before evaluation of the containing program or function begins. Evaluation of the literal produces a reference to that object; it does not create a new object. Two regular expression literals in a program evaluate to regular expression objects that never compare as === to each other even if the two literals' contents are identical.

There is no primitive regex type that autoboxes to an object in the same way as string or number.

Note, however, that not all browsers implement the "instantiate-once-per-literal" behavior, including Safari and IE6 (and possibly later), so portable code shouldn't depend on it. The abortive ECMAScript 4 draft would have changed the behavior to match those browsers:

In ES3 a regular expression literal like /a*b/mg denotes a single unique RegExp object that is created the first time the literal is encountered during evaluation. In ES4 a new RegExp object is created every time the literal is encountered during evaluation.

Also, some browsers (Firefox <3, Safari) report typeof /regex/ as "function", so portable code should avoid typeof on RegExp instances—stick with instanceof.

Miles
  • 31,360
  • 7
  • 64
  • 74
  • Don't stick with `instanceof`. Stick with [[Class]] checking (http://thinkweb2.com/projects/prototype/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/) – kangax Aug 25 '09 at 22:44
  • Updated link http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ – Fabio Beltramini Dec 31 '14 at 14:34
  • Luckily, [ES5 *did* change this behaviour](https://stackoverflow.com/a/28184009/1048572) – Bergi Jul 08 '19 at 10:16
7

Yes, the following two expressions are equivalent:

var r1 = /ab+c/i,
    r2 =new RegExp("ab+c", "i");

The constructor property of both points to the RegExp constructor function:

(/ab+c/i).constructor === RegExp // true
r2.constructor === RegExp // true

And a regexp literal is an instance of RegExp:

 /ab+c/i instanceof RegExp // true

The basic difference is that defining regular expressions using the constructor function allows you to build and compile an expression from a string. This can be very useful for constructing complex expressions that will be re-used.

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • You are correct, but the fact that the constructor property points to RegExp doesn't actually prove anything. "foo".constructor === String evaluates to true as well. – Matthew Crumley Aug 25 '09 at 06:43
1

Yes, new RegExp("something", "g") is the same as /something/g

Kamarey
  • 10,832
  • 7
  • 57
  • 70
  • Not exactly, with regards to special characters and escaping. With a regex literal, to match a single backspace, you do `/\\/`; with the constructor, you need `"\\\\"`. – Miles Aug 25 '09 at 06:30
  • That is because the constructor requires a string argument but regex literals have their own syntax. This does not answer the question though :( – KJ Saxena Aug 25 '09 at 06:34
  • 1
    @Miles: but at the end you get instance of RegExp in both cases. The question was not "what syntax difference between these two cases". – Kamarey Aug 25 '09 at 06:57