用途?
用於給url
中的特殊字元進行編碼。
為什麼要用?
因為網路標準RFC1738
做了硬性規定,只有字元和數字以及一些規定內的特殊符號,才可以不經過編碼用於url
,換言之就是,如果你的url
中包含了規定之外的符號,那它就是非法的url
, 無法被伺服器解析,也就無法訪問到你想要的網路資源。
為瞭解決這個問題,js
就提供了encodeURI
和encodeURIComponent
來給這些規定之外的符號進行編碼,這樣,伺服器就能正常解析並訪問了。
用法?
encodeURI
encodeURI()會編碼除去ASCII碼、數字和~!@#$&*()=:/,;?+.-_'
之外的所有字元。
const url = 'http://www.test.com/images/花朵.png'
const nextUrl = encodeURI(url)
// http://www.test.com/images/%E8%8A%B1%E6%9C%B5.png
encodeURIComponent
encodeURIComponent()會編碼除去ASCII碼、數字和~!*().-_'
之外的所有字元。
const url = 'http://www.test.com/images/花朵.png'
const nextUrl = encodeURIComponent(url)
// http%3A%2F%2Fwww.test.com%2Fimages%2F%E8%8A%B1%E6%9C%B5.png
兩者之間的差異
encodeURIComponent會進行編碼的字元範圍比encodeURI大。
兩者之間如何選用
由於兩者之間唯一的差異就是可被編碼的字元範圍,所以需要根據實際需要編碼的字元做抉擇。
情況1:
const url = 'http://www.test.com/images/花朵.png'
console.log(encodeURI(url));
http://www.test.com/images/%E8%8A%B1%E6%9C%B5.png
console.log(encodeURIComponent(url));
http%3A%2F%2Fwww.test.com%2Fimages%2F%E8%8A%B1%E6%9C%B5.png
透過上面的示例我們發現,由於encodeURIComponent
的編碼範圍很廣,如果對整個URL
呼叫,會導致URL
中有特殊作用的符號被編碼,變成一個非法的URL
了,也就無法訪問了。所以此種情況應該選用encodeURI
。
情況2:
const name = 'AT&T';
console.log(encodeURI(name));
// AT&T
console.log(encodeURIComponent(name));
// AT%26T
由於encodeURI
的編碼範圍較小,導致此處我們希望被編碼的&
並沒有被編碼。所以此種情況應該選用encodeURIComponent
。
應用場景
場景1:
url引數中包含特殊字元
// 美國電話電報公司
const name = 'AT&T';
const url = `http://www.test.com?name=${name}`;
const nextUrl = new URL(url);
const search = new URLSearchParams(nextUrl.search);
console.log(search.get('name'));
// AT
輸出的結果缺少了一部分,這是因為&
是一個標準的url
引數分割符,所以會被解析為分割符。雖然如此,但本例中的&
符號是屬於名字的一部分,我們不想讓它被解析為url
的引數分隔符。這時我們就可以使用encodeURIComponent
對name
的值進行編碼,這樣&
就不會被識別為引數分割符了
// 美國電話電報公司
const name = 'AT&T';
const url = `http://www.test.com?name=${encodeURIComponent(name)}`;
const nextUrl = new URL(url);
const search = new URLSearchParams(nextUrl.search);
console.log(search.get('name'));
// AT&T
場景2:
將一個回撥地址作為引數附加在另一個地址上
const redirectUrl = 'http://www.result.com?type=success&num=10';
const targetUrl = `http://www.test.com?redirectUrl=${redirectUrl}`;
const url = new URL(targetUrl);
const search = new URLSearchParams(url.search);
console.log(search.get('redirectUrl'));
// http://www.result.com?type=success
我們獲取redirectUrl
引數時,會發現num
引數丟失了,這是因為&
被當成www.test.com
的引數分隔符了,這裡我們可以使用encodeURIComponent
來對redirectUrl
進行編碼就能解決這個問題。
const redirectUrl = 'http://www.result.com?type=success&num=10';
const targetUrl = `http://www.test.com?redirectUrl=${encodeURIComponent(redirectUrl)}`;
const url = new URL(targetUrl);
const search = new URLSearchParams(url.search);
console.log(search.get('redirectUrl'));
// http://www.result.com?type=success&num=10
疑問
現代瀏覽器會自動識別URL
中的特殊字元並將其編碼,那還需要我們手動呼叫encodeURI
和encodeURIComponent
嗎?
答案是看情況,比如在引數中有中文的情況下,中文在URL
中不會有歧義(中文在URL
中不會有其它含義),所以瀏覽器會幫你完成編碼,但是,在有些情況下,瀏覽器是不知道你是否需要編碼的,我們拿前面的一個示例:
// 美國電話電報公司
const name = 'AT&T';
這裡的&
在URL
中有兩種含義,一是作為引數分割符,二是作為普通的字元,這時,瀏覽器無法猜測你的意圖,也就不會幫你自動編碼了,所以,還是需要你主動呼叫encodeURIComponent
。
注意事項
- 他們對特殊字元的編碼形式是
utf-8