带你了解前端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('&'));
复制代码
相关文章
相关标签/搜索