为何URL构造函数不会对查询字符串中的括号进行编码?
P粉287254588
2023-09-03 21:05:00
<p>在JavaScript中,当括号和圆括号出现在查询字符串中时,<code>URL</code>构造函数不会对它们进行编码,而<code>encodeURI</code>或<code>encodeURIComponent</code>总是会对它们进行编码。这让我感到困惑,因为大多数来源都说在查询参数中包含特殊字符时要使用<code>encodeURI</code>/<code>encodeURIComponent</code>进行编码。我期望<code>URL</code>对象具有类似的行为。</p>
<p>这导致我在编写单元测试时遇到问题,因为我不知道URL对象的查询参数将如何进行编码。是否有规范来说明这一点,还是我应该在使用<code>URL</code>构造函数之前始终对参数进行编码?谢谢您的帮助。</p>
<hr />
<p>示例显示URL对象在查询字符串中不对括号进行编码</p>
<pre class="brush:js;toolbar:false;">const href = (new URL('https://foobar.com?myQuery={"@asdf/asdf":"1234"}')).href;
// ^ https://foobar.com/?myQuery={%22@asdf/asdf%22:%221234%22}
</pre>
<p>如果我使用<code>encodeURI</code>,唯一的区别就是括号被编码了</p>
<pre class="brush:js;toolbar:false;">const href = encodeURI('https://foobar.com?myQuery={"@asdf/asdf":"1234"}');
// ^ https://foobar.com?myQuery=%7B%22@asdf/asdf%22:%221234%22%7D
</pre>
<hr />
<p>注意:如果括号不在查询参数中,URL对象会对其进行编码。</p>
<pre class="brush:js;toolbar:false;">const href = (new URL('https://foobar.com/}}}?myQuery={"@asdf/asdf":"1234"}')).href;
// ^ https://foobar.com/%7D%7D%7D?myQuery={%22@asdf/asdf%22:%221234%22}
</pre></p>
有多种可能的编码方式,它们都应该被解释为相同的URL,因此从技术上讲都不是错误的。另一个例子是百分比编码可以使用大写或小写字符(
%aa
或%AA
),域名不区分大小写,空格可以被编码为+
或%20
(在某些部分)。如果您想对特定的URL编码实现进行单元测试,可以进行字符串匹配,但如果您想知道两个URL是否相同,无论它们是如何编码的,您首先需要进行一步称为“规范化”的操作,然后再进行比较。