encodeURI VS encodeURIComponent

發表於2023-09-24

用途?

用於給url中的特殊字元進行編碼。

為什麼要用?

因為網路標準RFC1738做了硬性規定,只有字元和數字以及一些規定內的特殊符號,才可以不經過編碼用於url,換言之就是,如果你的url中包含了規定之外的符號,那它就是非法的url, 無法被伺服器解析,也就無法訪問到你想要的網路資源。
為了解決這個問題,js就提供了encodeURIencodeURIComponent來給這些規定之外的符號進行編碼,這樣,伺服器就能正常解析並訪問了。

用法?

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的引數分隔符。這時我們就可以使用encodeURIComponentname的值進行編碼,這樣&就不會被識別為引數分割符了

// 美國電話電報公司
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中的特殊字元並將其編碼,那還需要我們手動呼叫encodeURIencodeURIComponent嗎?
答案是看情況,比如在引數中有中文的情況下,中文在URL中不會有歧義(中文在URL中不會有其它含義),所以瀏覽器會幫你完成編碼,但是,在有些情況下,瀏覽器是不知道你是否需要編碼的,我們拿前面的一個示例:

// 美國電話電報公司
const name = 'AT&T';

這裡的&URL中有兩種含義,一是作為引數分割符,二是作為普通的字元,這時,瀏覽器無法猜測你的意圖,也就不會幫你自動編碼了,所以,還是需要你主動呼叫encodeURIComponent

注意事項

  • 他們對特殊字元的編碼形式是utf-8

相關文章