最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Testing for equality of regular expressions - Stack Overflow

programmeradmin1浏览0评论

I was surprised to see that

/a/ === /a/

evaluates to false in JavaScript. Reading through the specs:

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.

Since === cannot be used to test for equality, how can equality of regular expressions be tested in JavaScript?

I was surprised to see that

/a/ === /a/

evaluates to false in JavaScript. Reading through the specs:

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.

Since === cannot be used to test for equality, how can equality of regular expressions be tested in JavaScript?

Share Improve this question asked May 27, 2012 at 19:19 RandomblueRandomblue 116k150 gold badges362 silver badges557 bronze badges 8
  • Go through this JavaScript === vs == : Does it matter which “equal” operator I use? – Siva Charan Commented May 27, 2012 at 19:24
  • 6 You're talking about JavaScript, the language in which [] == [] evaluates to False. – Tyler Crompton Commented May 27, 2012 at 19:25
  • 3 @SivaCharan how is that useful? – Matt Ball Commented May 27, 2012 at 19:25
  • 3 @TylerCrompton: don't forget [] == [].length. This question might answer the original question, or at least nudge OP in the right direction. – user1233508 Commented May 27, 2012 at 19:28
  • 1 There's nothing special going on here - this is expected and logical behaviour. RegExp is not a special object, like strings, objects, and arrays - you wouldn't expect new MyClass(x) === new MyClass(x) to be true either. – Eric Commented May 27, 2012 at 19:32
 |  Show 3 more comments

5 Answers 5

Reset to default 22

Here's a case that even covers ordering of flags.

function regexEqual(x, y) {
    return (x instanceof RegExp) && (y instanceof RegExp) && 
           (x.source === y.source) && (x.global === y.global) && 
           (x.ignoreCase === y.ignoreCase) && (x.multiline === y.multiline);
}

Tests:

regexEqual(/a/, /a/) // true
regexEqual(/a/gi, /a/ig) // also true.
regeXEqual(/a/, /b/) // false

Here's a function that fully tests all the relevant regex properties and makes sure it's the right type of object:

function regexSame(r1, r2) {
    if (r1 instanceof RegExp && r2 instanceof RegExp) {
        var props = ["global", "multiline", "ignoreCase", "source", "dotAll", "sticky", "unicode"];
        for (var i = 0; i < props.length; i++) {
            var prop = props[i];
            if (r1[prop] !== r2[prop]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

And, since flags sometimes get added to the regex object with new features (as has happened since this original answer in 2012 - though the above code has been updated as of 2019), here's a version that is a bit more future proof on future flags being added since it compares whatever flags are there rather than looking for a specific set of flags. It sorts the flags before comparing to allow for minor differences in how the regex was specified that wouldn't not actually change functionality.

function regexSame(r1, r2) {
    return r1 instanceof RegExp && 
           r2 instanceof RegExp &&
           r1.source === r2.source &&
           r1.flags.split("").sort().join("") === r2.flags.split("").sort().join("");
}

You can check the types with typeof, then toString() both regexes and compare those. It won't cover cases with equivalent flags, such as /a/gi and /a/ig, though.

function regexEquals(a, b)
{
    if (typeof a !== 'object' || typeof b !== 'object') return false;

    return a.toString() === b.toString();
}

Unfortunately there's no more-specific type from typeof, so if you really want to make sure they're regexes (or regex-like) you could do something along these lines:

RegExp.prototype.regexEquals = function (other)
{
    return (typeof other.regexEquals === 'function')
        && (this.toString() === other.toString());
}

Then:

/a/.regexEquals(/a/); // true
/a/.regexEquals(/b/); // false

Compare them using toString(), and check their type too:

var a = /a/,
    b = /a/;

a.toString() === b.toString() && typeof(a) === typeof(b)  //true

var c = /a/,
    d = /b/;

c.toString() === d.toString() && typeof(c) === typeof(d)  //false

Answers above didn't consider case-sensitivity. So built upon jfriend00's answer, the function should be

function regexEqual(a, b) {
    if (!(a instanceof RegExp) || !(b instanceof RegExp)) {
        return false;
    }
    let sourceA = a.source;
    let sourceB = b.source;
    const flagsA = a.flags.split('').sort().join(',');
    const flagsB = b.flags.split('').sort().join(',');
    if (flagsA.includes('i') && flagsB.includes('i')) {
        sourceA = sourceA.toLowerCase();
        sourceB = sourceB.toLowerCase();
    }
    return sourceA === sourceB && flagsA === flagsB;
}
发布评论

评论列表(0)

  1. 暂无评论