187

Is there anyway to detect if a JavaScript object is a regex?

For example, I would like to do something like this:

var t = /^foo(bar)?$/i;
alert(typeof t); //I want this to return "regexp"

Is this possible?

Thanks!

EDIT: Thanks for all the answers. It seems I have two very good choices:

obj.constructor.name === "RegExp"

or

obj instanceof RegExp

Any major pros/cons to either method?

Thanks again!

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
tau
  • 6,499
  • 10
  • 37
  • 60
  • 1
    See [this answer](http://stackoverflow.com/questions/3215046/differentiating-between-arrays-and-hashes-in-javascript/3215440#3215440) to another question for concerns with the use of `instanceof` and `constructor`. – user113716 Dec 02 '10 at 20:26
  • 1
    Hi, I don't think putting answers in your question is very relevant. Please consider to add your own answer if you think you can add something useful :) – TOPKAT Jan 23 '20 at 15:59

9 Answers9

251

You can use instanceof operator:

var t = /^foo(bar)?$/i;
alert(t instanceof RegExp);//returns true

In fact, that is almost the same as:

var t = /^foo(bar)?$/i;
alert(t.constructor == RegExp);//returns true

Keep in mind that as RegExp is not a primitive data type, it is not possible to use typeof operator which could be the best option for this question.

But you can use this trick above or others like duck type checking, for example, checking if such object has any vital methods or properties, or by its internal class value (by using {}.toString.call(instaceOfMyObject)).

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Cleiton
  • 17,663
  • 13
  • 46
  • 59
  • 1
    awesome. do you know which is faster/more compatible: using your instanceof method or the constructor.name method? thanks! – tau Dec 02 '10 at 20:10
  • 1
    instanceof, of course, you can verify it yourself using Firebug Timing(console.time) – Cleiton Dec 02 '10 at 20:18
  • 13
    Those two code snippets are not identical. If you inserted the line `t.constructor = function() {};`, which is perfectly legal, then `t instanceof RegExp` will still be true but `t.constructor == RegExp` will be false. Using `instanceof` is therefore preferable. – Tim Down Dec 03 '10 at 10:45
  • 16
    Also, `t instanceof RegExp` will report false when testing a regular expression object from another window, which won't be a problem if this kind of check is not required, but is something to be aware of. – Tim Down Dec 03 '10 at 10:49
  • 1
    Also, when using in "if/else if" and you checked before for (typeof t === 'object') : add either -> && !(_t instanceof RegExp) to this check or if possible perform Cleiton's check first. [tl;dr : it is also typeof object, just important if used in "if/else if" ...] – sebilasse Jun 16 '15 at 14:39
24
alert( Object.prototype.toString.call( t ) ); // [object RegExp]

This is the way mentioned in the specification for getting the class of object.

From ECMAScript 5, Section 8.6.2 Object Internal Properties and Methods:

The value of the [[Class]] internal property is defined by this specification for every kind of built-in object. The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String". The value of a [[Class]] internal property is used internally to distinguish different kinds of objects. Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString (see 15.2.4.2).

A RegExp is a class of object defined in the spec at Section 15.10 RegExp(RegularExpression)Objects:

A RegExp object contains a regular expression and the associated flags.

user113716
  • 318,772
  • 63
  • 451
  • 440
  • 4
    @Tim - I'm pretty sure. Not that it's any guarantee, but it is the [method jQuery uses](https://github.com/jquery/jquery/blob/master/src/core.js#L504-508), including for [RegExp](https://github.com/jquery/jquery/blob/master/src/core.js#L821-823). I'll just did a quick test in IE6 using a RegExp, and it does work (if that's any indicator). :o) Appears as though this method made it into the spec in the 3rd edition. – user113716 Dec 03 '10 at 13:07
  • 1
    Unfortunately this doesn't work in IE with RegExp objects from other windows, for the same reason that the `[object Array]` check doesn't work for arrays. See http://www.jsfiddle.net/F6d8u/ for a demo and https://groups.google.com/group/comp.lang.javascript/browse_frm/thread/368a55fec19af7b2/efea4aa2d12a3aa4?hl=en&lnk=gst&q=+An+isArray+test+%28and+IE+bugs%29+#efea4aa2d12a3aa4 for a discussion of this. – Tim Down Dec 03 '10 at 13:28
  • 3
    Apart from duck typing, which is irritatingly inexact, this is still the best answer. – Tim Down Dec 03 '10 at 13:31
  • @Tim - Interesting. I'm going to take a closer look at the example and article in a little bit when I have a chance to fire up IE again. Thanks for the input. – user113716 Dec 03 '10 at 13:51
  • In Node.js it returns `[object String]` so it's not helpful... Possibly because it's across contexts. – Alexis Wilke Nov 27 '18 at 06:48
14

Give the .constructor property a whirl:

> /^foo(bar)?$/i.constructor
function RegExp() { [native code] }
> /^foo(bar)?$/i.constructor.name
"RegExp"
> /^foo(bar)?$/i.constructor == RegExp
true
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
11

From underscore.js

// Is the given value a regular expression?
  _.isRegExp = function(obj) {
    return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
  };
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • 1
    They're duck typing here because `typeof` is unreliable for regexes and `instanceof` suffers from the cross-window problem. I wonder why they're not using @patrick dw's answer... – Tim Down Dec 03 '10 at 10:57
  • 3
    Now I know: it doesn't work in IE when examining objects from other windows. – Tim Down Dec 03 '10 at 13:30
  • @Tim -- awesome ... I was wondering the same thing, but didn't have time to check yet. Thanks for posting the answer here! – Sean Vieira Dec 03 '10 at 14:14
  • 6
    Underscore now uses `Object.prototype.toString.call(obj) == '[object RegExp]'` – nickf Sep 13 '13 at 10:22
3

Works in google chrome:

x = /^foo(bar)?$/i;
x == RegExp(x); // true
y = "hello";
y == RegExp(y); // false
Vladimir Lagunov
  • 1,895
  • 15
  • 15
0

There is no absolute way of checking this, so far the best answer is

var t = /^foo(bar)?$/i;
alert(t instanceof RegExp);//returns true

but there is one down side to this approach and that's it will return false if the regular expression object is commeing from an other window.

Iman Mohamadi
  • 6,552
  • 3
  • 34
  • 33
0

Here are two ways:

/^\/.*\/$/.test(/hi/) /* test regexp literal via regexp literal */
/^\/.*\/$/.test(RegExp("hi") ) /* test RegExp constructor via regexp literal */
RegExp("^/" + ".*" + "/$").test(/hi/) /* test regexp literal via RegExp constructor */
RegExp("^/" + ".*" + "/$").test(RegExp("hi") ) /* test RegExp constructor via RegExp constructor */ 

delete RegExp("hi").source /* test via deletion of the source property */
delete /hi/.global /* test via deletion of the global property */
delete /hi/.ignoreCase /* test via deletion of the ignoreCase property */
delete RegExp("hi").multiline /* test via deletion of the multiline property */
delete RegExp("hi").lastIndex /* test via deletion of the lastIndex property */

If a string literal is delimited by the regexp backslash delimiter, the regexp self test will fail.

If Object.seal or Object.freeze are run on a user-defined object, and that object also has all of the aforementioned properties, the delete statement will return a false positive.

References

Community
  • 1
  • 1
Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
  • I do not understand your answer. – Tino Jan 17 '16 at 15:00
  • @Tino RegExp types have two unique characteristics. The literal values start and end with the `/` character. The constructor instances have the `source`, `global`, `ignoreCase`, `multiline`, and `lastIndex` properties. – Paul Sweatte Jan 17 '16 at 21:54
  • Thanks, but unfortunately following `frog` proves that these characteristics are **not unique** to `RegExp`s: `$$=function(){};$$.prototype.toString=function(){return "/I am not a duck^WRegExp/"};$$.prototype.source=$$.prototype.global=$$.prototype.ignoreCase=$$.prototype.multiline=$$.prototype.lastIndex="quack"; frog=new $$()` – Tino Jan 18 '16 at 03:20
  • @Tino That's why the `delete` keyword was used. If you `delete` them from an instance of a `RegExp` object, you will get a different result than if you delete them from a custom object or any other built-in which is customized. See an [unrelated question](http://stackoverflow.com/questions/7193412/what-are-some-use-cases-of-when-delete-has-been-very-useful-in-javascript/16951655#16951655) for further explanation. – Paul Sweatte Jan 18 '16 at 03:31
0

"Regexp" is not a native Javascript type. Most of the above answers tell you how to accomplish your task, but not why. Here's why.

  • 4
    That's a misleading answer. A regular expression most definitely is a native ECMAScript and JavaScript object. I think what you're getting at is that typeof's possible values do not include a dedicated value for regular expression. – Tim Down Dec 03 '10 at 10:53
  • `sed -i s/native/primitive/`. If you count `object` as primitive, `typeof t` only outputs the primitive type name (well. mostly. see https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/typeof). – Tino Jan 17 '16 at 15:14
0

I was looking for typeof regex because I tried use it in type definition for TypeScript props on a function.

Then I do the next:

const RegexType = /$/;

type paramProps = {
  regexParam: typeof RegexType;
}

You can test here:

const RegexType = /$/;
const t = /^foo(bar)?$/i;

console.log(typeof t == typeof RegexType) //true