我正在乱搞QUnit,我偶然发现了一件事。
我在Chrome上尝试了这个简单的测试:
deepEqual(new RegExp(), /(?:)/);
我认为它会通过,因为new RegExp()
会在开发者控制台中返回/(?:)/
。对于new RegExp() === /(?:)/
来说,似乎不能“只”执行RegExp
,但两者的toString()
函数都返回相同而 相等。
我认为文字/非文字符号会产生影响,但自从此测试通过以来情况并非如此:
deepEqual(new RegExp(" "), / /);
因此,从以下测试中,第一次失败:
test("test", function() {
deepEqual(new RegExp(), /(?:)/); // fail
deepEqual(new RegExp(" "), / /); // pass
equal(new RegExp().toString(), /(?:)/.toString()); // pass
});
因此,有人可以指出我正确的方向,为什么第一次测试失败了吗?
答案 0 :(得分:3)
简短回答:source
属性的值与正则表达式文字/(?:)/
和从new RegExp()
获得的对象不同。在文字的情况下它是/(?:)/
,而在对象的情况下,它是一个空字符串。执行/ /
和new RegExp(" ")
时,source
属性的值相同(两者都是包含一个空格字符的字符串)。
长答案:如果你看一下Qunit的来源,你会看到这段代码:
"regexp": function (b, a) {
return QUnit.objectType(b) === "regexp" &&
a.source === b.source && // the regex itself
a.global === b.global && // and its modifers (gmi) ...
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
};
您可以使用此代码查看源参数的不同之处(它只是输出每个正则表达式参数的属性并测试它们是否相等):
function eq(x, y) {
console.log("x.source:", "'" + x.source + "'", "y.source:", "'" + y.source + "'", "===:", x.source === y.source);
console.log("x.global:", x.global, "y.global:", y.global, "===:", x.global === y.global);
console.log("x.ignoreCase:", x.ignoreCase, "y.ignoreCase:", y.ignoreCase, "===:", x.ignoreCase === y.ignoreCase);
console.log("x.multiline:", x.multiline, "y.multiline:", y.multiline, "===:", x.multiline === y.multiline);
}
当您使用eq(/(?:)/, new RegExp());
拨打此电话时,您会收到:
x.source: '(?:)' y.source: '' ===: false
x.global: false y.global: false ===: true
x.ignoreCase: false y.ignoreCase: false ===: true
x.multiline: false y.multiline: false ===: true
当你用eq(/ /, new RegExp(" "));
打电话时,你会得到:
x.source: ' ' y.source: ' ' ===: true
x.global: false y.global: false ===: true
x.ignoreCase: false y.ignoreCase: false ===: true
x.multiline: false y.multiline: false ===: true