帶你瞭解前端URL編解碼那些事

坐雲獨酌杯盤溼,穿竹微吟路徑斜。javascript

URL URN 仍是URI?

escape 和 unescape 又是什麼?

decodeURI encodeURIComponent 有什麼區別?

URL URN 仍是URI

URI定義

URI(Uniform Resource Identifier,統一資源標識符):一個資源的惟一標識。HTTP 請求的內容通稱爲"資源"。」資源「這一律念很是寬泛,它能夠是一份文檔,一張圖片,或全部其餘你可以想到的格式。每一個資源都由一個 (URI) 來進行標識。java

URL定義

URL(Uniform Resource Locator,統一資源定位器):也被稱做web地址,它是一種具體的URI,即URL能夠用來標識一個資源,並且還指明瞭如何定位這個資源(網絡位置)。通俗地說,URL是Internet上用來描述資源的字符串,主要用在各類www客戶端和服務器程序。web

URN定義

URN(Universal Resource Name, 統一資源名稱):URN是基於某命名空間經過名稱指定資源的URI。人們能夠經過URN來指出某個資源,而無需指出其位置和得到方式。資源無需是基於互聯網的。瀏覽器

URI

URI能夠分爲URL,URN或同時具有locators 和names特性的一個東西。URN做用就好像一我的的名字,URL就像一我的的地址。換句話說:URN肯定了東西的名稱,URL提供了找到它的方式,而URI表明資源的惟一標識。安全

URL和URN都是URI的子集。服務器

  • ftp://ftp.is.co.za/rfc/rfc1808.txt (also a URL because of the protocol)
  • www.ietf.org/rfc/rfc2396… (also a URL because of the protocol)
  • ldap://[2001:db8::7]/c=GB?objectClass?one (also a URL because of the protocol)
  • mailto:John.Doe@example.com (also a URL because of the protocol)
  • news:comp.infosystems.www.servers.unix (also a URL because of the protocol)
  • tel:+1-816-555-1212
  • telnet://192.0.2.16:80/ (also a URL because of the protocol)
  • urn:oasis:names:specification:docbook:dtd:xml:4.1.2

URL編解碼

"只有字母和數字[0-9a-zA-Z]、一些特殊符號"$-_.+!*'(),"[不包括雙引號]、以及某些保留字,才能夠不通過編碼直接用於URL。"網絡

若是URL中有漢字,就必須編碼後使用,可是麻煩的是,RFC1738沒有規定具體的編碼方法, 而是交給應用程序(瀏覽器)本身決定,這致使'URL編碼'成爲了一個混亂的領域.。函數

接下來咱們介紹一下URL編解碼的幾種方式。ui

escape 和 unescape

該特性已經從 Web 標準中刪除,雖然一些瀏覽器目前仍然支持它,但也許會在將來的某個時間中止支持,請儘可能不要使用該特性。this

古老的escape()不能直接用於URL編碼,它的真正做用是返回一個字符的Unicode編碼值。 它的具體規則是,除了ASCII字母、數字、標點符號"@ * _ + - . /"之外,對其餘全部字符進行編碼。在u0000到u00ff之間的符號被轉成%xx的形式,其他符號被轉成%uxxxx的形式。對應的解碼函數是unescape()。

escape("王總");   
escape("abc123");
escape("@*_+-./"); 
escape("http://www.bingshangroup.com?name=王總&slogen=屬實"); 

// %u738B%u603B
// abc123
// @*_+-./
// http%3A//www.bingshangroup.com%3Fname%3D%u738B%u603B%26slogen%3D%u5C5E%u5B9E
複製代碼

encodeURI 和 decodeURI

它着眼於對整個URL進行編碼,所以除了常見的符號之外,對其餘一些在網址中有特殊含義的符號也不進行編碼。編碼後,它輸出符號的utf-8形式,而且在每一個字節前加上%。

它對應的解碼函數是decodeURI()。

encodeURI 會替換全部的字符,但不包括如下字符,即便它們具備適當的UTF-8轉義序列:

類型 包含
保留字符 ; , / ? : @ & = + $
非轉義的字符 字母 數字 - _ . ! ~ * ' ( )
數字符號 #
encodeURI('http://www.bingshangroup.com?name=王總&slogen=屬實');
encodeURI('http://www.bingshangroup.com?group=wangzong&mayi=web');

// http://www.bingshangroup.com?name=%E7%8E%8B%E6%80%BB&slogen=%E5%B1%9E%E5%AE%9E
// http://www.bingshangroup.com?group=wangzong&mayi=web
複製代碼

& = 不會被編碼,然而在 GET 和 POST 請求中它們是特殊字符,致使了請求參數獲取的錯誤

encodeURIComponent 和 decodeURIComponent

與encodeURI()的區別是,它用於對URL的組成部分進行個別編碼,而不用於對整個URL進行編碼。 它對應的解碼函數是decodeURIComponent()。

encodeURIComponent 轉義除了字母 數字 ( ) . ! ~ * ' -_以外的全部字符。

encodeURIComponent('http://www.bingshangroup.com?name=王總&slogen=屬實');
encodeURIComponent('http://www.bingshangroup.com?group=wangzong&mayi=web');

// http%3A%2F%2Fwww.bingshangroup.com%3Fname%3D%E7%8E%8B%E6%80%BB%26slogen%3D%E5%B1%9E%E5%AE%9E
// http%3A%2F%2Fwww.bingshangroup.com%3Fgroup%3Dwangzong%26mayi%3Dweb
複製代碼

講點其餘

RFC 3986

爲了更嚴格的遵循 RFC 3986(保留 ! ' ( )*),即便這些字符並無正式劃定 URI 的用途,下面這種方式是比較安全的:

function fixedEncodeURIComponent (str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
複製代碼

[]保留給了IPV6

function fixedEncodeURI (str) {
    return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']');
}
複製代碼

如何把對象轉換成查詢字符串

var objectToQueryString = (obj) => Object.keys(obj).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');
objectToQueryString({name:王總, slogen:屬實})
複製代碼

又或者你能夠這樣玩(想一下原理是什麼)

class FormData {
    constructor(key, value) {
        this.key = key;
        this.value = value;
    }
    
    toString() {
        return encodeURIComponent(this.key) + '=' + encodeURIComponent(this.value);
    }
}

let items = [
    new FormData('王總', '屬實'),
    new FormData('mayi', 'yahei')
];

console.log(items.join('&'));
複製代碼
相關文章
相關標籤/搜索