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