URL详解以及encodeURI、encodeURIComponent、decodeURI、decodeURIComponent的区别

标签: JavaScript  学习  url  编码

1.URL详解

1.1 URL 与 URI

很多人会混淆这两个名词。

  • URL:(Uniform/Universal Resource Locator 的缩写,统一资源定位符)。
  • URI:(Uniform Resource Identifier 的缩写,统一资源标识符)。是用来标识互联网上的资源(例如,网页或文件)和怎样访问这些资源的传输协议(例如,HTTP 或 FTP)的字符串。

【关系】:

  • URI 属于 URL 更低层次的抽象,一种字符串文本标准。
  • 就是说,URI 属于父类,而 URL 属于 URI 的子类。URL 是 URI 的一个子集。

【区别】:

  • URI 表示请求服务器的路径,定义这么一个资源。
  • 而 URL 同时说明要如何访问这个资源(http://)。
1.2 端口 与 URL标准格式

何为端口?
端口(Port),相当于一种数据的传输通道。用于接受某些数据,然后传输给相应的服务,而电脑将这些数据处理后,再将相应的回复通过开启的端口传给对方。

端口的作用:因为 IP 地址与网络服务的关系是一对多的关系。所以实际上因特网上是通过 IP 地址加上端口号来区分不同的服务的。

端口是通过端口号来标记的,端口号只有整数,范围是从0 ~65535。

URL 标准格式
通常而言,我们所熟悉的 URL 的常见定义格式为:
scheme://host[:port#]/path/.../[;url-params][?query-string][#anchor]
例如:http://abc.com:8080/dir/index.html?id=255&m=hello#top

scheme //有我们很熟悉的http、https、ftp以及著名的ed2k,迅雷的thunder等。
host   //HTTP服务器的IP地址或者域名 'abc'
port#  //HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如tomcat的默认端口是8080 http://localhost:8080/
path   //访问资源的路径
url-params  //所带参数
query-string    //发送给http服务器的数据
anchor //锚点定位
1.3 利用 <a> 标签自动解析 url

开发当中一个很常见的场景是,需要从 URL 中提取一些需要的元素,譬如 host 、 请求参数等等。

通常的做法是写正则去匹配相应的字段,当然,这里要安利下述这种方法,原理是动态创建一个 a 标签,利用浏览器的一些原生方法及一些正则(为了健壮性正则还是要的),完美解析 URL ,获取我们想要的任意一个部分。

代码如下:

function parseURL(url) {
  var a = document.createElement('a')
  a.href = url
  return {
    source: url,
    protocol: a.protocol.replace(':', ''),
    host: a.hostname,
    port: a.port,
    query: a.search,
    params: (function () {
      var ret = {},
        seg = a.search.replace(/^\?/, '').split('&'),
        len = seg.length, i = 0, s
      for (; i < len; i++) {
        if (!seg[i]) {
          continue
        }
        s = seg[i].split('=')
        ret[s[0]] = s[1]
      }
      return ret
    })(),
    file: (a.pathname.match(/([^/?#]+)$/i) || [, ''])[1],
    hash: a.hash.replace('#', ''),
    path: a.pathname.replace(/^([^/])/, '/$1'),
    relative: (a.href.match(/tps?:\/[^/]+(.+)/) || [, ''])[1],
    segments: a.pathname.replace(/^\//, '').split('/')
  }
}

用法:

var myURL = parseURL('http://abc.com:8080/dir/index.html?id=255&m=hello#top')

console.log(myURL.file)     // => 'index.html'
console.log(myURL.hash)     // => 'top'
console.log(myURL.host)     // => 'abc.com'
console.log(myURL.query)    // => '?id=255&m=hello'
console.log(myURL.params)   // => Object = { id: 255, m: hello }
console.log(myURL.path)     // => '/dir/index.html'
console.log(myURL.segments) // => Array = ['dir', 'index.html']
console.log(myURL.port)     // => '8080'
console.log(myURL.protocol) // => 'http'
console.log(myURL.source)   // => 'http://abc.com:8080/dir/index.html?id=255&m=hello#top'

2.encodeURI、encodeURIComponent、decodeURI、decodeURIComponent

2.1. 用来编码和解码URI的

通常如果一样东西需要编码,说明这样东西并不适合传输。原因多种多样,如Size过大,包含隐私数据,对于URL来说,之所以要进行编码,是因为URL中有些字符会引起歧义。

例如,URL参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收URL的服务器解析错误,因此必须将引起歧义的&=符号进行转义,也就是对其进行编码。

又如,URL 的编码格式采用的是ASCII码,而不是Unicode,这也就是说你不能在URL中包含任何非ASCII字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

encodeURIencodeURIComponentdecodeURIdecodeURIComponent四个用来编码和解码 URI 的函数之外 ECMAScript 语言自身不提供任何使用 URL 的支持。

注: 许多 ECMAScript 实现提供额外的函数,方法来操作网页;这些函数超出了本标准的范围。

2.2 有何不同?

encodeURIdecodeURI 函数操作的是完整的 URI;这俩函数假定 URI 中的任何保留字符都有特殊意义,所有不会编码它们。

不会编码的字符有82个: !#$&’()*+,/:;[email protected]_~0-9a-zA-Z

encodeURI("https://blog.csdn.net/season-qxj/some other thing");
// "https://blog.csdn.net/season-qxj/some%20other%20thing"
encodeURI("[email protected]#$&*()=:/,;?+'")
// [email protected]#$&*()=:/,;?+'

👆可以看到空格被编码成了%20,而斜杠 /冒号 :等并没有被编码。

encodeURIComponentdecodeURIComponent 函数操作的是组成 URI 的个别组件;这俩函数假定任何保留字符都代表普通文本,所以必须编码它们,所以它们(保留字符)出现在一个完整 URI 的组件里面时不会被解释成保留字符了。

不会编码的字符有71个:!’()*-._~0-9a-zA-Z

有时我们的 URL 长这样子,请求参数中带了另一个 URL :

var URL = "http://www.a.com?foo=http://www.b.com?t=123&s=456";

若直接对它进行 encodeURI 显然是不行的,因为 encodeURI 不会对冒号 :斜杠 /进行转义。

encodeURI(URL)
// "http://www.a.com?foo=http://www.b.com?t=123&b=456"

此时就该用到 encodeURIComponent() 对 URL 中的参数(仅仅是参数)进行编码。因为它仅仅不对 ASCII字母数字 ~ ! * ( ) ' 进行编码。

错误的用法:

var URL = "http://www.a.com?foo=http://www.b.com?t=123&s=456";
encodeURIComponent(URL);
// "http%3A%2F%2Fwww.a.com%3Ffoo%3Dhttp%3A%2F%2Fwww.b.com%3Ft%3D123%26s%3D456"
// 错误的用法,第一个 http 的冒号及斜杠也被 encode 了

正确的用法: encodeURIComponent() 着眼于对单个的参数进行编码:

var param = "http://www.b.com?t=123&s=456"; // 要被编码的参数
URL = "http://www.a.com?foo="+encodeURIComponent(param);
//"http://www.a.com?foo=http%3A%2F%2Fwww.b.com%3Ft%3D123%26s%3D456"
2.3 图解四个函数的不同

ECMA对这四个函数还做了详细解释,不过看得我云里雾里,👇有大神做了简单详细的图解:
样例

图源网络

【总结】:利用👆的使用<a>标签解析 URL 以及根据业务场景配合 encodeURI()encodeURIComponent()便能够很好的处理 URL 的编码问题。

【好用工具】:URL编码解码
【参考资料】:【基础进阶】URL详解与URL编码
【附录】:常用ASCII URL编码对照表

版权声明:本文为a1056244734原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a1056244734/article/details/107689148

智能推荐

PoolThreadCache

缓存构成   PoolThreadCache的缓存由三部分构成:tiny、small 和 normal。 tiny   缓存数据大小区间为[16B, 496B]数据,数组长度为32,根据数据大小计算索引的办法:数据大小除以16,如下代码所示: small   缓存数据大小区间为[512B, 4KB]数据,数组长度为4,根据数据大小计算索引的办法:数据大小除以512,然后log2得到指数,如下代码所...

Intellij IDEA 搭建Spring Boot项目(一)

Intellij IDEA 搭建Spring Boot项目 标签(空格分隔): SpringBoot JAVA后台 第一步 选择File –> New –> Project –>Spring Initialer –> 点击Next  第二步 自己修改 Group 和 Artif...

CentOS学习之路1-wget下载安装配置

参考1: https://blog.csdn.net/zhaoyanjun6/article/details/79108129 参考2: http://www.souvc.com/?p=1569 CentOS学习之路1-wget下载安装配置 1.wget的安装与基本使用 安装wget yum 安装软件 默认安装保存在/var/cache/yum ,用于所有用户使用。 帮助命令 基本用法 例子:下载...

深入浅出Spring的IOC容器,对Spring的IOC容器源码进行深入理解

文章目录 DispatcherServlet整体继承图 入口:DispatcherServlet.init() HttpServletBean.init() FrameworkServlet.initServletBean() 首先大家,去看Spring的源码入口,第一个就是DispatcherServlet DispatcherServlet整体继承图 入口:DispatcherServlet....

laravel框架的课堂知识点概总

1. MVC 1.1 概念理解 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑 MVC 是一种使用 MVC(Model View Controller ...

猜你喜欢

Unity人物角色动画系统学习总结

使用动画系统控制人物行走、转向、翻墙、滑行、拾取木头 混合树用来混合多个动画 MatchTarget用来匹配翻墙贴合墙上的某一点,人物以此为支点翻墙跳跃 IK动画类似于MatchTarget,控制两只手上的两个点来指定手的旋转和位置,使得拾取木头时更逼真 创建AnimatorController: 首先创建一个混合树,然后双击 可以看到该混合树有五种状态机,分别是Idle、WalkForward、...

Composer 安装 ThinkPHP6 问题

Composer 安装 ThinkPHP6 问题 先说说问题 一.运行环境要求 二.配置 参考: ThinkPHP6.0完全开发手册 先说说问题 执行ThinkPHP6的安装命令 遇到问题汇总如下: 看提示是要更新版本,执行命令更新。 更新之后,再次安装ThinkPHP,之后遇到如下问题。 尝试了很多方法,依然不能解决。其中包括使用https://packagist.phpcomposer.com...

Spring Boot 整合JDBC

今天主要讲解一下SpringBoot如何整合JDBC,没啥理论好说的,直接上代码,看项目整体结构 看一下对应的pom.xml 定义User.java 定义数据源配置,这里使用druid,所以需要写一个配置类 上面指定druid的属性配置,和用户登录的账号信息以及对应的过滤规则: 下面定义数据访问接口和对应的实现: 数据访问层很简单,直接注入JdbcTemplate模板即可,下面再看对应的servi...

html鼠标悬停显示样式

1.显示小手:     在style中添加cursor:pointer 实现鼠标悬停变成小手样式     实例:         其他参数: cursor语法: cursor : auto | crosshair | default | hand | move | help | wait | tex...

Yupoo(又拍网)的系统架构

Yupoo!(又拍网) 是目前国内最大的图片服务提供商,整个网站构建于大量的开源软件之上。以下为其使用到的开源软件信息: 操作系统:CentOS、MacOSX、Ubuntu 服务器:Apache、Nginx、Squid 数据库:MySQLmochiweb、MySQLdb 服务器监控:Cacti、Nagios、 开发语言:PHP、Python、Erlang、Java、Lua 分布式计算:Hadoop...