我们知道在Web前端存在多种类型的编码,比如URL中的%xxx
、图片src
的data:ZmRy...
等。 这些编码和解码过程会用到不同的编解码函数,本文来介绍不同编码的编码方式以及使用场景。
escape对应的解码函数是unescape
,它们已经从Web标准中废弃。绝大多数情况都可以使用encodeURI
和encodeURIComponent
来代替。
escape
将会转义除了@*_+-./
以外的所有字符,当小于0xFF
时表示为%xx
,大于时表示为%uxxxx
。例如:
escape("abc123"); // "abc123"
escape("äöü"); // "%E4%F6%FC"
escape("ć"); // "%u0107"
// 特殊字符
escape("@*_+-./"); // "@*_+-./"
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是用来编码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(binary-to-alphabet)的解码函数为atob
,它们可以进行二进制到文本的编码,这种编码规则称为Base64编码。 Base64字符集中的字符包括26个字母的大小写(52个)、数字(10个)以及+
和/
。 得到的文本大小是原二进制大小的4/3,因为原本6位( 26=64 )能够编码的信息现在需要8位(ASCII的一个字节)来编码。
Base64通常用于将二进制文件编码到HTML或者URL中,方便在Web应用中传输。 有些文本编辑器中,会将你的图片直接编码为Base64格式插入到HTML中,而不是将它存为单独的图片文件。 例如下面的代码将会生成这个红点:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
这里稍微解释一下为什么Base64编码的最后会出现几个等号:
二进制文件是按字节存储的,每字节表示的信息是8位;Base64每一个编码字符表示的信息是6位。 它们最小公倍数是24,编码时以24位为单位进行处理最为方便。比如下面是一个可行的编码方式:
为了能够正确解码,当原数据长度不是3的倍数时,差几个就在编码结束加几个=
。 所以Base64编码的字符串中通常包含65个字符,字符集中的64个加上保留字=
。
注意JavaScript String的字符是16位(UTF-8)存储的,不能直接用它进行测试。如果要编码UTF-8字符,
btoa
可能会发生溢出,最好先进行encodeURIComponent
。
除非注明,本博客文章均为原创,转载请以链接形式标明本文地址: http://harttle.com/2015/08/17/js-escape.html