URL 对象
- 创建 URL 对象:new URL(url, [base])
- url —— 完整的 URL,或者仅路径(如果设置了 base),
- base —— 可选的 base URL:如果设置了此参数,且参数 url 只有路径,则会根据这个 base 生成 URL。
- URL 组件
- href 是完整的 URL,与 url.toString() 相同
- protocol 以冒号字符 : 结尾
- search —— 以问号 ? 开头的一串参数
- hash 以哈希字符 # 开头
- 如果存在 HTTP 身份验证,则这里可能还会有 user 和 password 属性:http://login:password@site.com(图片上没有,很少被用到)。
- 我们可以将 URL 对象传递给网络(和大多数其他)方法,而不是字符串
- 我们可以在 fetch 或 XMLHttpRequest 中使用 URL 对象,几乎可以在任何需要 URL 字符串的地方都能使用 URL 对象。
- 通常,URL 对象可以替代字符串传递给任何方法,因为大多数方法都会执行字符串转换,这会将 URL 对象转换为具有完整 URL 的字符串。
SearchParams “?…”
- url.searchParams,URLSearchParams 类型的对象。
- append(name, value) —— 按照 name 添加参数,
- delete(name) —— 按照 name 移除参数,
- get(name) —— 按照 name 获取参数,
- getAll(name) —— 获取相同 name 的所有参数(这是可行的,例如 ?user=John&user=Pete),
- has(name) —— 按照 name 检查参数是否存在,
- set(name, value) —— set/replace 参数,
- sort() —— 按 name 对参数进行排序,很少使用,
- ……并且它是可迭代的,类似于 Map。
- 包含空格和标点符号的参数:参数会被自动编码
// 遍历搜索参数(被解码)
for(let [name, value] of url.searchParams) {
alert(`${name}=${value}`); // q=test me!,然后是 tbs=qdr:y
}
编码(encoding)
- RFC3986 标准定义了 URL 中允许哪些字符,不允许哪些字符。
- 那些不被允许的字符必须被编码,例如非拉丁字母和空格 —— 用其 UTF-8 代码代替,前缀为 %,例如 %20(由于历史原因,空格可以用 + 编码,但这是一个例外)。
- 好消息是 URL 对象会自动处理这些。我们仅需提供未编码的参数,然后将 URL 转换为字符串:
- 正如你所看到的,url 路径中的 Тест 和 ъ 参数都被编码了。
- URL 变长了,因为每个西里尔字母用 UTF-8 编码的两个字节表示,因此这里有两个 %.. 实体(entities)。
编码字符串
- 在过去,在出现 URL 对象之前,人们使用字符串作为 URL。URL 对象通常更方便,但是仍然可以使用字符串。在很多情况下,使用字符串可以使代码更短。
- 如果使用字符串,则需要手动编码/解码特殊字符。下面是用于编码/解码 URL 的内建函数:
- encodeURI —— 编码整个 URL。
- decodeURI —— 解码为编码前的状态。
- encodeURIComponent —— 编码 URL 组件,例如搜索参数,或者 hash,或者 pathname。
- decodeURIComponent —— 解码为编码前的状态。
- 一个自然的问题:“encodeURIComponent 和 encodeURI 之间有什么区别?我们什么时候应该使用哪个?”如果我们看一个 URL,就容易理解了,它被分解为本文上面图中所示的组件形式:
- https://site.com:8080/path/page?p1=v1&p2=v2#hash
- 在 URL 中 :,?,=,&,# 这类字符是被允许的。
- ……另一方面,对于 URL 的单个组件,例如一个搜索参数,则必须对这些字符进行编码,以免破坏 URL 的格式。
- encodeURI 仅编码 URL 中完全禁止的字符。
- encodeURIComponent 也编码这类字符,此外,还编码 #,$,&,+,,,/,:,;,=,? 和 @ 字符。
- 所以,对于一个 URL 整体,我们可以使用 encodeURI:
- let url = encodeURI('http://site.com/привет');
- alert(url); // http://site.com/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
- ……而对于 URL 参数,我们应该改用 encodeURIComponent:
- let music = encodeURIComponent('Rock&Roll');
- let url = `https://google.com/search?q=${music}`;
- alert(url); // https://google.com/search?q=Rock%26Roll
- 将其与 encodeURI 进行比较:
- let music = encodeURI('Rock&Roll');
- let url = `https://google.com/search?q=${music}`;
- alert(url); // https://google.com/search?q=Rock&Roll
- encodeURI 没有对 & 进行编码,因为它对于整个 URL 来说是合法的字符。
- 但是,我们应该编码在搜索参数中的 & 字符,否则,我们将得到 q=Rock&Roll —— 实际上是 q=Rock 加上某个晦涩的参数 Roll。不符合预期。
- 因此,对于每个搜索参数,我们应该使用 encodeURIComponent,以将其正确地插入到 URL 字符串中。最安全的方式是对 name 和 value 都进行编码,除非我们能够绝对确保它只包含允许的字符。