Javascript 正则表达式的相等性测试

Javascript 正则表达式的相等性测试,javascript,Javascript,看到这一点我很惊讶 /a/ === /a/ 在JavaScript中计算为false。通读: 程序中的两个正则表达式文本计算为正则表达式 即使 两个文本的内容相同 既然==不能用于测试相等性,那么如何在JavaScript中测试正则表达式的相等性呢?您可以使用typeof检查类型,然后toString()两个正则表达式并比较它们。但是,它不包括具有等效标志的情况,例如/a/gi和/a/ig function regexEquals(a, b) { if (typeof a !== 'o

看到这一点我很惊讶

/a/ === /a/
在JavaScript中计算为
false
。通读:

程序中的两个正则表达式文本计算为正则表达式 即使 两个文本的内容相同


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

您可以使用
typeof
检查类型,然后
toString()
两个正则表达式并比较它们。但是,它不包括具有等效标志的情况,例如
/a/gi
/a/ig

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

    return a.toString() === b.toString();
}
不幸的是,
typeof
中没有更具体的类型,因此,如果您真的想确保它们是正则表达式(或类似正则表达式),您可以按照以下方式进行操作:

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


使用
toString()
比较它们,并检查它们的
类型

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

这里有一个案例甚至涵盖了旗帜的排序

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

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

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

以上回答没有考虑病例敏感性。基于此,功能应该是

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

仔细看一下你所说的JavaScript,
[]=[]
计算结果为
False
@SivaCharan这有什么用?@TylerCrompton:别忘了
[]=[].length
。可能会回答最初的问题,或者至少将OP推向正确的方向。这里没有什么特别的事情——这是预期的和合乎逻辑的行为
RegExp
不像字符串、对象和数组那样是一个特殊的对象-你也不会期望
new MyClass(x)===new MyClass(x)
是真的。这与调用
.toString()
不一样吗?@Eric:不….toString()返回你输入的确切内容。这将使用预定义的标志顺序来确保/a/gi==/a/ig.非常好。我不知道
.source
&co+1@JohnathonArka:啊,没有考虑标志的顺序。您没有检查所有标志,只有
g
i
m
。例如,对于函数,
regexEqual(/a/s,/a/)
将返回true。您还需要检查
dotAll
s
)、
unicode
u
)和
sticky
y
)属性。您可以找到标志的完整列表。您没有检查所有标志,只有
g
i
m
。例如,对于函数,
regexSame(/a/s,/a/)
将返回true。您还需要检查
dotAll
s
)、
unicode
u
)和
sticky
y
)属性。您可以找到完整的标志列表。@DonaldDuck-好的,我添加了这些属性。我不确定这些属性在2012年写下这个答案时是否被记录(甚至可能被支持)。无论如何,它现在已经更新了。@DonaldDuck-我添加了一个更具未来证明的版本,将来添加新标志时将继续工作。从2019-12-06起,Edge不支持正则表达式中的flags属性。第一个答案可能是一个更好的主意,直到Edge支持他们为止。@DanHooper-希望这很快就会出现,因为Edge正在切换到Chromium引擎。我想这也意味着Chrome JS引擎。您还可以使用
x instanceof RegExp
检查
x
是否是regex。
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("");
}
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;
}