15

我很惊讶地看到

/a/ === /a/

false在 JavaScript 中计算为。通读规格

程序中的两个正则表达式文字评估为永远不会相互比较 === 的正则表达式对象,即使这两个文字的内容相同。

既然===不能用来测试相等性,那么如何在 JavaScript 中测试正则表达式的相等性呢?

4

5 回答 5

20

这是一个甚至涵盖标志排序的案例。

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);
}

测试:

regexEqual(/a/, /a/) // true
regexEqual(/a/gi, /a/ig) // also true.
regeXEqual(/a/, /b/) // false
于 2012-05-27T19:28:37.227 回答
7

这是一个完全测试所有相关正则表达式属性并确保它是正确类型的对象的函数:

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;
}

而且,由于标志有时会被添加到具有新功能的正则表达式对象中(自 2012 年这个原始答案以来发生的情况 - 尽管上述代码已于 2019 年更新),所以这里的版本对未来标志有更多的未来证明被添加是因为它比较那里的任何标志而不是寻找一组特定的标志。它在比较之前对标志进行排序,以允许指定正则表达式的方式存在细微差异,而这些差异实际上不会改变功能。

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("");
}
于 2012-05-27T19:36:34.180 回答
2

您可以检查类型typeof,然后检查toString()两个正则表达式并进行比较。但是,它不会涵盖具有等效标志的情况,例如/a/giand /a/ig

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

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

不幸的是,没有更具体的类型 from typeof,所以如果你真的想确保它们是正则表达式(或类似正则表达式),你可以按照以下方式做一些事情:

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

然后:

/a/.regexEquals(/a/); // true
/a/.regexEquals(/b/); // false
于 2012-05-27T19:22:32.283 回答
2

使用 比较它们toString(),并检查它们type

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
于 2012-05-27T19:24:42.883 回答
0

上面的答案没有考虑区分大小写。所以建立在jfriend00 的答案上,函数应该是

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;
}
于 2019-11-21T05:15:19.470 回答