为什么 URL class 不支持为 http(s) 以外的协议设置用户名?

Why the URL class does not support setting username for protocols other than http(s)?

考虑以下代码:

const url = new URL('mumble://example.com');
url.username = 'user';
console.log(url.toString()); // prints "mumble://example.com"

但相同的代码适用于 http:

const url = new URL('http://example.com');
url.username = 'user';
console.log(url.toString()); // prints "http://user@example.com/"

我在文档中找不到有关该行为的任何信息。我的目标的解决方法很有趣:

const url = new URL('mumble://example.com');
const protocol = url.protocol;
url.protocol = 'http:';
url.username = 'user';
url.protocol = protocol;
console.log(url.toString()); // prints "mumble://user@example.com/"

谁能解释一下?

编辑:有趣的是,URL class 不支持设置更多属性,只要协议不是 http 或 https:

const url = new URL('mumble://example.com');
const protocol = url.protocol;
url.username = 'user';
url.pathname = 'foo';
url.port = 21;
url.protocol = protocol;
url.host = 'foo.bar';
console.log(url.toString()); // still mumble://example.com

并非所有方案都支持用户名。例如,file 没有。您的 JS 引擎显然假定未知方案不支持用户名。

Firefox 中的 URL class 和 Chrome 不完全符合 the URL spec,所以你的问题的答案是 URL class 的规范 确实 允许这样做,但是您所在的环境 运行 您的代码所在的环境还不符合规范。

例如,运行 您在 Node 14.x 中的示例代码确实输出了 mumble://user@example.com,正如您希望的那样。

您的选择是解决您支持的环境中的当前行为,或者加载像 whatwg-url 这样的 polyfill,这将允许您使用 URL API如你所料。