W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎勵
內(nèi)建的 URL 類提供了用于創(chuàng)建和解析 URL 的便捷接口。
沒有任何一個(gè)網(wǎng)絡(luò)方法一定需要使用 URL
對象,字符串就足夠了。所以從技術(shù)上講,我們并不是必須使用 URL
。但是有些時(shí)候 URL
對象真的很有用。
創(chuàng)建一個(gè)新 URL
對象的語法:
new URL(url, [base])
url
? —— 完整的 URL,或者僅路徑(如果設(shè)置了 base),base
? —— 可選的 base URL:如果設(shè)置了此參數(shù),且參數(shù) ?url
? 只有路徑,則會根據(jù)這個(gè) ?base
? 生成 URL。例如:
let url = new URL('https://javascript.info/profile/admin');
下面這兩個(gè) 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
我們可以根據(jù)相對于現(xiàn)有 URL 的路徑輕松創(chuàng)建一個(gè)新的 URL:
let url = new URL('https://javascript.info/profile/admin');
let newUrl = new URL('tester', url);
alert(newUrl); // https://javascript.info/profile/tester
URL
對象立即允許我們訪問其組件,因此這是一個(gè)解析 url 的好方法,例如:
let url = new URL('https://javascript.info/url');
alert(url.protocol); // https:
alert(url.host); // javascript.info
alert(url.pathname); // /url
這是 URL 組件的備忘單:
href
? 是完整的 URL,與 ?url.toString()
? 相同protocol
? 以冒號字符 ?:
? 結(jié)尾search
? —— 以問號 ??
? 開頭的一串參數(shù)hash
? 以哈希字符 ?#
? 開頭user
? 和 ?password
? 屬性:?http://login:password@site.com
?(圖片上沒有,很少被用到)。我們可以將 ?
URL
? 對象傳遞給網(wǎng)絡(luò)(和大多數(shù)其他)方法,而不是字符串我們可以在
fetch
或XMLHttpRequest
中使用URL
對象,幾乎可以在任何需要 URL 字符串的地方都能使用URL
對象。
通常,
URL
對象可以替代字符串傳遞給任何方法,因?yàn)榇蠖鄶?shù)方法都會執(zhí)行字符串轉(zhuǎn)換,這會將URL
對象轉(zhuǎn)換為具有完整 URL 的字符串。
假設(shè),我們想要創(chuàng)建一個(gè)具有給定搜索參數(shù)的 url,例如:https://google.com/search?query=JavaScript
。
我們可以在 URL 字符串中提供它們:
new URL('https://google.com/search?query=JavaScript')
……但是,如果參數(shù)中包含空格,非拉丁字母等(具體參見下文),參數(shù)就需要被編碼。
因此,有一個(gè) URL 屬性用于解決這個(gè)問題:url.searchParams
,URLSearchParams 類型的對象。
它為搜索參數(shù)提供了簡便的方法:
append(name, value)
? —— 按照 ?name
? 添加參數(shù),delete(name)
? —— 按照 ?name
? 移除參數(shù),get(name)
? —— 按照 ?name
? 獲取參數(shù),getAll(name)
? —— 獲取相同 ?name
? 的所有參數(shù)(這是可行的,例如 ??user=John&user=Pete
?),has(name)
? —— 按照 ?name
? 檢查參數(shù)是否存在,set(name, value)
? —— set/replace 參數(shù),sort()
? —— 按 name 對參數(shù)進(jìn)行排序,很少使用,Map
?。包含空格和標(biāo)點(diǎn)符號的參數(shù)的示例:
let url = new URL('https://google.com/search');
url.searchParams.set('q', 'test me!'); // 添加帶有一個(gè)空格和一個(gè) ! 的參數(shù)
alert(url); // https://google.com/search?q=test+me%21
url.searchParams.set('tbs', 'qdr:y'); // 添加帶有一個(gè)冒號 : 的參數(shù)
// 參數(shù)會被自動編碼
alert(url); // https://google.com/search?q=test+me%21&tbs=qdr%3Ay
// 遍歷搜索參數(shù)(被解碼)
for(let [name, value] of url.searchParams) {
alert(`${name}=${value}`); // q=test me!,然后是 tbs=qdr:y
}
RFC3986 標(biāo)準(zhǔn)定義了 URL 中允許哪些字符,不允許哪些字符。
那些不被允許的字符必須被編碼,例如非拉丁字母和空格 —— 用其 UTF-8 代碼代替,前綴為 %
,例如 %20
(由于歷史原因,空格可以用 +
編碼,但這是一個(gè)例外)。
好消息是 URL
對象會自動處理這些。我們僅需提供未編碼的參數(shù),然后將 URL
轉(zhuǎn)換為字符串:
// 在此示例中使用一些西里爾字符
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 路徑中的 Тест
和 ъ
參數(shù)都被編碼了。
URL 變長了,因?yàn)槊總€(gè)西里爾字母用 UTF-8 編碼的兩個(gè)字節(jié)表示,因此這里有兩個(gè) %..
實(shí)體(entities)。
在過去,在出現(xiàn) URL
對象之前,人們使用字符串作為 URL。
而現(xiàn)在,URL
對象通常更方便,但是仍然可以使用字符串。在很多情況下,使用字符串可以使代碼更短。
如果使用字符串,則需要手動編碼/解碼特殊字符。
下面是用于編碼/解碼 URL 的內(nèi)建函數(shù):
一個(gè)自然的問題:“encodeURIComponent
和 encodeURI
之間有什么區(qū)別?我們什么時(shí)候應(yīng)該使用哪個(gè)?”
如果我們看一個(gè) URL,就容易理解了,它被分解為本文上面圖中所示的組件形式:
https://site.com:8080/path/page?p1=v1&p2=v2#hash
正如我們所看到的,在 URL 中 :
,?
,=
,&
,#
這類字符是被允許的。
……另一方面,對于 URL 的單個(gè)組件,例如一個(gè)搜索參數(shù),則必須對這些字符進(jìn)行編碼,以免破壞 URL 的格式。
encodeURI
? 僅編碼 URL 中完全禁止的字符。encodeURIComponent
? 也編碼這類字符,此外,還編碼 ?#
?,?$
?,?&
?,?+
?,?,
?,?/
?,?:
?,?;
?,?=
?,??
? 和 ?@
? 字符。所以,對于一個(gè) 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 參數(shù),我們應(yīng)該改用 encodeURIComponent
:
let music = encodeURIComponent('Rock&Roll');
let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock%26Roll
將其與 encodeURI
進(jìn)行比較:
let music = encodeURI('Rock&Roll');
let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock&Roll
我們可以看到,encodeURI
沒有對 &
進(jìn)行編碼,因?yàn)樗鼘τ谡麄€(gè) URL 來說是合法的字符。
但是,我們應(yīng)該編碼在搜索參數(shù)中的 &
字符,否則,我們將得到 q=Rock&Roll
—— 實(shí)際上是 q=Rock
加上某個(gè)晦澀的參數(shù) Roll
。不符合預(yù)期。
因此,對于每個(gè)搜索參數(shù),我們應(yīng)該使用 encodeURIComponent
,以將其正確地插入到 URL 字符串中。最安全的方式是對 name 和 value 都進(jìn)行編碼,除非我們能夠絕對確保它只包含允許的字符。
?
encode*
? 與 ?URL
? 之間的編碼差異URL 和 URLSearchParams 基于最新的 URL 規(guī)范:RFC3986,而
encode*
函數(shù)是基于過時(shí)的 RFC2396。
它們之間有一些區(qū)別,例如對 IPv6 地址的編碼方式不同:
// IPv6 地址的合法 url let url = 'http://[2607:f8b0:4005:802::1007]/'; alert(encodeURI(url)); // http://%5B2607:f8b0:4005:802::1007%5D/ alert(new URL(url)); // http://[2607:f8b0:4005:802::1007]/
正如我們所看到的,
encodeURI
替換了方括號[...]
,這是不正確的,原因是:在 RFC2396 (August 1998) 時(shí)代,還不存在 IPv6 url。
這種情況很少見,
encode*
函數(shù)在大多數(shù)情況下都能正常工作。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: