LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 398|回复: 0

编码字符串

[复制链接]
发表于 2024-1-31 22:54:29 | 显示全部楼层 |阅读模式
在过去,在出现 URL 对象之前,人们使用字符串作为 URL。

而现在,URL 对象通常更方便,但是仍然可以使用字符串。在很多情况下,使用字符串可以使代码更短。

如果使用字符串,则需要手动编码/解码特殊字符。

下面是用于编码/解码 URL 的内建函数:

encodeURI —— 编码整个 URL。
decodeURI —— 解码为编码前的状态。
encodeURIComponent —— 编码 URL 组件,例如搜索参数,或者 hash,或者 pathname。
decodeURIComponent —— 解码为编码前的状态。
一个自然的问题:“encodeURIComponent 和 encodeURI 之间有什么区别?我们什么时候应该使用哪个?”

如果我们看一个 URL,就容易理解了,它被分解为本文上面图中所示的组件形式:

https://site.com:8080/path/page?p1=v1&p2=v2#hash
正如我们所看到的,在 URL 中 :,?,=,&,# 这类字符是被允许的。

……另一方面,对于 URL 的单个组件,例如一个搜索参数,则必须对这些字符进行编码,以免破坏 URL 的格式。

encodeURI 仅编码 URL 中完全禁止的字符。
encodeURIComponent 也编码这类字符,此外,还编码 #,$,&,+,,,/,:,;,=,? 和 @ 字符。
所以,对于一个 URL 整体,我们可以使用 encodeURI:

// 在 url 路径中使用西里尔字符
let url = encodeURI('http://site.com/привет');

alert(url); // http://site.com/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
……而对于 URL 参数,我们应该改用 encodeURIComponent:

let music = encodeURIComponent('Rock&Roll');

let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock%26Roll
将其与 encodeURI 进行比较:

let music = encodeURI('Rock&Roll');

let url = `https://google.com/search?q=${music}`;
alert(url); // https://google.com/search?q=Rock&Roll
我们可以看到,encodeURI 没有对 & 进行编码,因为它对于整个 URL 来说是合法的字符。

但是,我们应该编码在搜索参数中的 & 字符,否则,我们将得到 q=Rock&Roll —— 实际上是 q=Rock 加上某个晦涩的参数 Roll。不符合预期。

因此,对于每个搜索参数,我们应该使用 encodeURIComponent,以将其正确地插入到 URL 字符串中。最安全的方式是对 name 和 value 都进行编码,除非我们能够绝对确保它只包含允许的字符。

encode* 与 URL 之间的编码差异
URL 和 URLSearchParams 基于最新的 URL 规范:RFC3986,而 encode* 函数是基于过时的 RFC2396。

它们之间有一些区别,例如对 IPv6 地址的编码方式不同:

// IPv6 地址的合法 url
let url = 'http://[2607:f8b0:4005:802::1007]/';

alert(encodeURI(url)); // http://%5B2607:f8b0:4005:802::1007%5D/
alert(new URL(url)); // http://[2607:f8b0:4005:802::1007]/
正如我们所看到的,encodeURI 替换了方括号 [...],这是不正确的,原因是:在 RFC2396 (August 1998) 时代,还不存在 IPv6 url。

这种情况很少见,encode* 函数在大多数情况下都能正常工作。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表