为什么这个QUnit RegExp测试失败?

Why does this QUnit RegExp test fail?

本文关键字:测试 失败 RegExp QUnit 为什么      更新时间:2023-09-26

我正在摆弄QUnit,有一件事我偶然发现了。

我在Chrome上做了这个简单的测试:

deepEqual(new RegExp(), /(?:)/);

我认为它会通过,因为new RegExp()在开发人员控制台中返回/(?:)/。似乎不可能"只是"为RegExp s做new RegExp() === /(?:)/,但两者的toString()函数返回相同且相等。

我认为文字/非文字表示法会有区别,但事实并非如此,因为这个测试通过了:

deepEqual(new RegExp(" "), / /);

因此,从以下测试中,第一个失败:

test("test", function() {
    deepEqual(new RegExp(), /(?:)/); // fail
    deepEqual(new RegExp(" "), / /); // pass
    equal(new RegExp().toString(), /(?:)/.toString()); // pass
});

因此,有人可以指出我在正确的方向,为什么第一次测试失败,请?

简短的回答: source属性的值对于regex-literal /(?:)/和您从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;
};

您可以使用以下代码看到源参数的不同之处(它只是输出每个regex参数的属性并测试它们是否相等):

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