js對(duì)url進(jìn)行編碼和解碼

為什么要URL編碼?

在因特網(wǎng)上傳送URL,只能采用ASCII字符集

也就是說URL只能使用英文字母、阿拉伯?dāng)?shù)字和某些標(biāo)點(diǎn)符號(hào),不能使用其他文字和符號(hào),即
只有字母和數(shù)字[0-9a-zA-Z]、一些特殊符號(hào)$-_.+!*()、以及某些保留字(空格轉(zhuǎn)換為+)才可以不經(jīng)過編碼直接用于URL

這意味著 如果URL中有漢字,就必須編碼后使用
但是麻煩的是 標(biāo)準(zhǔn)的國際組織并沒有規(guī)定具體的編碼方法,而是交給應(yīng)用程序(瀏覽器)自己決定。 這導(dǎo)致"URL編碼"成為了一個(gè)混亂的領(lǐng)域。

如果包含中文,其實(shí)會(huì)自動(dòng)編碼的,比如Chrome和火狐,"文"和"章"的utf-8編碼分別是"E6 96 87"和"E7 AB A0" ,下圖所示的"%e6%96%87%e7%ab%a0"就是按照順序,在每個(gè)字節(jié)前加上%而得到的:



但是不同的瀏覽器可能會(huì)有不同的編碼方式,不要將編碼交給瀏覽器。應(yīng)該用JS在前端對(duì)URL編碼,這樣就實(shí)現(xiàn)了統(tǒng)一

如何編碼?

URL編碼通常也被稱為百分號(hào)編碼(percent-encoding),是因?yàn)樗木幋a方式非常簡單:
使用%加上兩位的字符——0123456789ABCDEF——代表一個(gè)字節(jié)的十六進(jìn)制形式。URL編碼要做的,就是將每一個(gè)非安全的ASCII字符都被替換為“%xx”格式,
對(duì)于非ASCII字符,RFC文檔建議使用utf-8對(duì)其進(jìn)行編碼得到相應(yīng)的字節(jié),然后對(duì)每個(gè)字節(jié)執(zhí)行百分號(hào)編碼。
如"中文"使用UTF-8字符集得到的字節(jié)為0xE4 0xB8 0xAD 0xE6 0x96 0x87,經(jīng)過Url編碼之后得到"%E4%B8%AD%E6%96%87"。

一些常見的特殊字符換成相應(yīng)的十六進(jìn)制的值:

+   %20   
/   %2F   
?   %3F   
%   %25   
#   %23   
&   %26  

假如我們有一個(gè)需要編碼的url:

var url = 'http://www.baidu.com?name=李曉韜&age=2'

現(xiàn)在分別用escapeencodeURI、encodeURIComponent 這三種方式編碼

escape(url) // http%3A//www.baidu.com%3Fname%3D%u674E%u6653%u97EC%26age%3D2
encodeURI(url) // http://www.baidu.com?name=%E6%9D%8E%E6%99%93%E9%9F%AC&age=2
encodeURIComponent(url) // http%3A%2F%2Fwww.baidu.com%3Fname%3D%E6%9D%8E%E6%99%93%E9%9F%AC%26age%3D2

漢字都被編碼了,貌似都沒問題,但是如果我們需要在瀏覽器中打開編碼后的url就有問題了,只有用encodeURI編碼的url可以在瀏覽器中打開

所以如果我們有這樣一個(gè)需求:

  • 接口傳給我們一個(gè)帶漢字的url
  • 拿到url后要用瀏覽器打開,如果有漢字在瀏覽器中打開可能會(huì)報(bào)錯(cuò),需要編碼

滿足以上兩個(gè)條件就必須用encodeURI編碼

以下是對(duì)這三種編碼方式的介紹:

只有 0-9[a-Z] $ - _ . + ! * ' ( ) , 以及某些保留字,才能不經(jīng)過編碼直接用于 URL

  1. escape 和 unescape
    原理:對(duì)除ASCII字母、數(shù)字、標(biāo)點(diǎn)符號(hào) @ * _ + - . / 以外的其他字符進(jìn)行編碼。

    編碼:escape('http://www.baidu.com?name=zhang@xiao@jie&order=1')
    結(jié)果:"http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1"
    編碼:escape('張')
    結(jié)果:"%u5F20"

    解碼:unescape("http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1")
    結(jié)果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
    解碼:unescape("%u5F20")
    結(jié)果:"張"

  2. encodeURI 和 decodeURI (推薦使用)
    原理:返回編碼為有效的統(tǒng)一資源標(biāo)識(shí)符 (URI) 的字符串,不會(huì)被編碼的字符:! @ # $ & * ( ) = : / ; ? + '
    encodeURI()是Javascript中真正用來對(duì)URL編碼的函數(shù)。
    用于:對(duì)整個(gè)url進(jìn)行編碼

    編碼:encodeURI('http://www.baidu.com?name=zhang@xiao@jie&order=1')
    結(jié)果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"

    解碼:decodeURI("http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1")
    結(jié)果:"http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1"

  3. encodeURIComponent 和 decodeURIComponent
    原理:對(duì)URL的組成部分進(jìn)行個(gè)別編碼,而不用于對(duì)整個(gè)URL進(jìn)行編碼
    用于:對(duì)url上的參數(shù)編碼

function param (data) {
  let url = ''
  for (var k in data) {
    let value = data[k] !== undefined ? data[k] : ''
    url += '&' + k + '=' + encodeURIComponent(value)
  }
  return url ? url.substring(1) : ''
}

編碼:encodeURIComponent('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結(jié)果:"http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1"

解碼:decodeURIComponent("http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1")
結(jié)果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容