我惊讶地发现
/a/ === /a/
在JavaScript中,正则表达式的比较值为false
。通过阅读规范文档:
程序中的两个正则表达式字面量将计算为永远不会相互比较为===,即使两个字面量的内容相同。
由于无法使用===
来测试相等性,因此如何在JavaScript中测试正则表达式的相等性?
我惊讶地发现
/a/ === /a/
在JavaScript中,正则表达式的比较值为false
。通过阅读规范文档:
程序中的两个正则表达式字面量将计算为永远不会相互比较为===,即使两个字面量的内容相同。
由于无法使用===
来测试相等性,因此如何在JavaScript中测试正则表达式的相等性?
这里有一个案例,甚至涉及到标志的排序。
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
.toString()
吗? - Eric.source
和其他的东西。+1 - Matt Ballg
、i
和 m
。例如,使用你的函数,regexEqual(/a/s, /a/)
将返回 true。你还需要检查 dotAll
(s
)、unicode
(u
) 和 sticky
(y
) 属性。你可以在这里找到完整的标志列表。 - Donald Duck这里有一个函数,可以完全测试所有相关的正则表达式属性,并确保它是正确类型的对象:
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 regexSame(r1, r2) {
return r1 instanceof RegExp &&
r2 instanceof RegExp &&
r1.source === r2.source &&
r1.flags.split("").sort().join("") === r2.flags.split("").sort().join("");
}
g
、i
和 m
。例如,使用你的函数,regexSame(/a/s, /a/)
将返回 true。你还需要检查 dotAll
(s
)、unicode
(u
) 和 sticky
(y
) 属性。你可以在这里找到完整的标志列表。 - Donald Ducktypeof
检查类型,然后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());
}
然后:
/a/.regexEquals(/a/); // true
/a/.regexEquals(/b/); // false
x instanceof RegExp
来检查 x
是否为正则表达式。 - Donald Duck使用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
上面的答案没有考虑大小写敏感性。因此,在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;
}
/\d/i
(一个数字)和 /\D/i
(一个非数字)。虽然在这些简单的示例中 /i
没有意义,但很明显,即使输入不区分大小写,正则表达式的源仍然可能是区分大小写的。 - Jacob Raihle
[] == []
的计算结果是False
。 - Tyler Crompton[] == [].length
。这个问题可能会回答原始问题,或者至少能引导 OP 往正确的方向。 - DCoderRegExp
不是一个特殊的对象,就像字符串、对象和数组一样 - 你也不会期望new MyClass(x) === new MyClass(x)
是 true 的。 - Eric