Web前端编码汇总:escape, encodeURI, encodeURIComponent

DOM HTML JavaScript UTF-8 字符串 字符编码

我们知道在Web前端存在多种类型的编码,比如URL中的%xxx、图片srcdata:ZmRy...等。 这些编码和解码过程会用到不同的编解码函数,本文来介绍不同编码的编码方式以及使用场景。

escape

escape对应的解码函数是unescape,它们已经从Web标准中废弃。绝大多数情况都可以使用encodeURIencodeURIComponent来代替。

escape将会转义除了@*_+-./以外的所有字符,当小于0xFF时表示为%xx,大于时表示为%uxxxx。例如:

escape("abc123");     // "abc123"
escape("äöü");        // "%E4%F6%FC"
escape("ć");          // "%u0107"

// 特殊字符
escape("@*_+-./");    // "@*_+-./"

encodeURI

encodeURI是用来编码URI的,最常见的就是编码一个URL。 encodeURI会将需要编码的字符转换为UTF-8的格式。与escape一样字符被编码后均以%起始。 但是对于保留字符(;,/?:@&=+$#),以及非转义字符(字母数字以及-_.!~*'())不会进行转义。

例如URL中包含中文:

encodeURI('http://www.我.com')   // => "http://www.%E6%88%91.com"

由于encodeURI不转义&, +, 和 =。所以URL参数的值是无法转义的,比如我们想把a=?传给服务器:

encodeURI('http://www.我.com?a=?')   // => "http://www.%E6%88%91.com?a=?"

服务器收到的a值为空,因为?是URL保留字符。此时我们需要用encodeURIComponent来编码!

encodeURIComponent

顾名思义,encodeURIComponent是用来编码URI参数的。它只会跳过非转义字符(字母数字以及-_.!~*'()), URL保留字符(;,/?:@&=+$#)均会被转义。比如上面的例子:

// => "http://www.我.com?a=%3F"
encodeURI('http://www.我.com') + '?a=' + encodeURIComponent('?');   

因为encodeURIComponent会编码所有的URL保留字,所以不适合编码URL,例如:

encodeURIComponent('http://www.我.com')
"http%3A%2F%2Fwww.%E6%88%91.com"

btoa

btoa(binary-to-alphabet)的解码函数为atob,它们可以进行二进制到文本的编码,这种编码规则称为Base64编码。 Base64字符集中的字符包括26个字母的大小写(52个)、数字(10个)以及+/。 得到的文本大小是原二进制大小的4/3,因为原本6位($2^6 = 64$)能够编码的信息现在需要8位(ASCII的一个字节)来编码。

Base64通常用于将二进制文件编码到HTML或者URL中,方便在Web应用中传输。 有些文本编辑器中,会将你的图片直接编码为Base64格式插入到HTML中,而不是将它存为单独的图片文件。 例如下面的代码将会生成这个红点:

Red dot

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

这里稍微解释一下为什么Base64编码的最后会出现几个等号:

二进制文件是按字节存储的,每字节表示的信息是8位;Base64每一个编码字符表示的信息是6位。 它们最小公倍数是24,编码时以24位为单位进行处理最为方便。比如下面是一个可行的编码方式:

  1. 拿出3个二进制字节,它们的信息是24位。
  2. 把这24位信息存为4个Base64字符。

为了能够正确解码,当原数据长度不是3的倍数时,差几个就在编码结束加几个=。 所以Base64编码的字符串中通常包含65个字符,字符集中的64个加上保留字=

注意JavaScript String的字符是16位(UTF-8)存储的,不能直接用它进行测试。如果要编码UTF-8字符,btoa可能会发生溢出,最好先进行encodeURIComponent

Harttle

致力于简单的、一致的、高效的前端开发

看看这个?