URL
URL 统一资源定位符是 URI 通用资源标识的特定类型。
URL 通常三或四个组成部分组成(第四部分可省略):
- 协议。它可以是 HTTP(不带 SSL)或 HTTPS(带 SSL)。
- 主机。例如:
cn.udacity.com
- 路径。例如:
/course/wechat-mini-program--nd666-cn-1
- 查询字符串。规则为?后显示参数查询值,伪 url 为:
?param1=value1¶m2=value2
综上,url 的书写规则为:http:/path/path/path?param1=value1¶m2=value2
不安全的空格
URL 中的空格会引入错误和不确定性,因此不允许出现空格,但是为了显示空格,浏览器会将空格替换为专门表示空格的特定代码 %20
。当在浏览器里输入 URL 时,浏览器会自动将空格替换为 %20
代码。但是,如果你使用 curl
从 shell 发出请求,则不会自动转换,因此你需要手动将空格替换为 %20
。
URL 对象
JavaScript 内建的 URL 类提供了用于创建和解析 URL 的便捷接口。虽然一般 url 字符串就足够了,但有些时候 URL
对象真的很有用,几乎可以在任何需要 URL 字符串的地方都能使用 URL
对象(作为替代方案),如在方法 fetch
或 XMLHttpRequest
中使用 URL
对象
URL 对象使用 URL
构造器创建
new URL(url, [base])
Tip
参数说明:
url
完整的 URL,或者仅路径(如果设置了 base)base
(可选)如果设置了此参数,且第一个参数url
只有路径,则会根据这个base
生成完整的 URL,该参数允许基于现有 URL 的路径轻松创建一个新的 URL
// 创建两个完全相同的 URL 对象
let url1 = new URL('https://javascript.info/profile/admin');
let url2 = new URL('/profile/admin', 'https://javascript.info');
alert(url1); // https://javascript.info/profile/admin
alert(url2); // https://javascript.info/profile/admin
// 基于已有的 URL 创建新的 URL
let url = new URL('https://javascript.info/profile/admin');
let newUrl = new URL('tester', url);
alert(newUrl); // https://javascript.info/profile/tester
URL
对象提供多种属性解析 url 以允许我们访问其中不同组件。
- 属性
href
是完整的 URL,与url.toString()
相同 - 属性
protocol
以冒号字符:
结尾 - 属性
search
以问号?
开头的一串参数 hash
以哈希字符#
开头- 属性
user
和password
如果存在 HTTP 身份验证,则 url 会有这两个值,如http://login:[email protected]
(示意图上没有,很少使用)
let url = new URL('https://javascript.info/url');
alert(url.protocol); // https:
alert(url.host); // javascript.info
alert(url.pathname); // /url
SearchParams
想要创建一个具有给定搜索参数的 url,如果参数中包含空格,非拉丁字母等,参数就需要被编码。使用 URL 对象属性 url.searchParams
提供的方法可以更方便地对搜索参数进行操作,它是 URLSearchParams 类型的对象,它是可迭代的,类似于 Map
,可用循环解构遍历该对象元素以获取所有搜索参数。
它为搜索参数提供了简便的方法:
append(name, value)
按照name=value
添加参数delete(name)
移除name
参数get(name)
获取name
参数的值getAll(name)
获取具有相同name
的所有参数的值(如?user=John&user=Pete
)has(name)
按照name
检查参数是否存在set(name, value)
类似 append 方法,但 set/replace 会删除其他已有的同名参数sort()
按 name 对参数进行排序,很少使用
let url = new URL('https://google.com/search');
url.searchParams.set('q', 'test me!'); // 添加带有一个空格和一个 ! 的参数
alert(url); // https://google.com/search?q=test+me%21,set 方法自动编码
url.searchParams.set('tbs', 'qdr:y'); // 添加带有一个冒号 : 的参数
// 参数会被自动编码
alert(url); // https://google.com/search?q=test+me%21&tbs=qdr%3Ay
// 遍历搜索参数(被解码)
for(let [name, value] of url.searchParams) {
alert(`${name}=${value}`); // q=test me!,然后是 tbs=qdr:y
}
编码
RFC3986 标准定义了 URL 中允许哪些字符,不允许哪些字符。那些不被允许的字符必须被编码,如非拉丁字母和空格,用其 UTF-8 代码代替,前缀为 %
,如空格用实体 entities %20
表示(由于历史原因,空格可以用 +
编码,但这是一个例外)。
URL
对象会自动对这些字符进行编码,我们仅需提供未编码的参数即可
// 在此示例中使用一些西里尔字符
let url = new URL('https://ru.wikipedia.org/wiki/Тест');
url.searchParams.set('key', 'ъ');
alert(url); //https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D1%81%D1%82?key=%D1%8A
// url 路径中的 Тест 和 ъ 参数都被编码了
// 每个西里尔字母用 UTF-8 编码的两个字节表示,即两个 %.. 实体
而如果使用字符串作为 URL,则需要手动编码/解码特殊字符。用于(手动)编码/解码 URL 的内建函数:
- encodeURI 编码整个 URL,仅处理 URL 中完全禁止的字符。
- decodeURI 解码为编码前的状态。
- encodeURIComponent 编码 URL 组件,除了处理 URL 完全禁止的字符以外,还编码 URL 组件中特殊的字符,包括
#
,$
,&
,+
,,
,/
,:
,;
,=
,?
和@
字符,以免破坏 URL 的格式(由于这些字符在 URL 组件中有特殊的作用)。 - decodeURIComponent 解码为编码前的状态。
// 对于一个 URL 整体使用 encodeURI 编码
// 在 url 路径中使用西里尔字符
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,没有对 & 进行编码,因为它对于整个 URL 来说是合法的字符
**/