在网络上以字符串方式传输数据的时候,因为某些字串作为控制符有特殊的含义,必须进行转码。这种机制是不可避免的,我们需要任何字符作为数据,没有哪个字符只作为控制字符不作为数据需要传输。最基本的转码其实就是引号表示字符串时候的反斜杠转义,没有这个转义规则,就无法把字串从代码中区分出来,不管你选什么字符作为字符串的标识,字符串要表示这个标识符的时候就必须转义,而且至少要两个转义符,一个是字串的表示界定符,一个是转义符。
网络协议需要更多的控制符,encodeURI就是把字符串进行转码,防止传输错误,而且非常彻底的,所有的转码函数都会把大量的字符集用ASCII码小于128的字符来编码,毕竟这样的“原始”字符,在各种场合处理起来都得心应手。
事实上encodeURI函数不编码字符只有82个:!,#,$,&,',(,),*,+,,,-,.,/,:,;,=,?,@,_,~,0-9,a-z,A-Z
后来因为有人用&=来连接url字串来传输数据,包括post,get都是用这种方式,所以“?”,“&”和“=”也成了控制符,也需要转码,还有其它原因,有必要弄两个级别的转码,这个函数就是encodeURIComponent,encodeURIComponent不编码字符有71个:!, ',(,),*,-,.,_,~,0-9,a-z,A-Z。
这样,把需要传输的数据用encodeURIComponent进行转码,再用?,&,=进行连接,一般来说,字串在传输前内部有可能自动进行encodeURI编码一次。所以encodeURI必须不转码这3个字符,而encodeURIComponent函数就必须转码这三个字符。
PHP有一个类似的函数urlencode(逆函数urldecode),但是这个函数更彻底,它会把除了“. _-”这3个字符以外的全部符号转码(当然还有大小写字母和10个数字,所有编码函数都不转码它们)。
实际上这些函数使用的编码规则是相同的,也就是通过“%”来指示编码,通过后面的HEX(16进制)数字来解码,所以理论上,任何字符都可以用这个规则来编码和解码,他们的区别就是对哪些字符编码,哪些字符不编码。所以理论上,解码是同一个函数。但是实际上并不是这样,encodeURIComponent和PHP的urlencode是可以互为解码的(这是错误的),而encodeURI不同,他会保留部分%号开头的编码不转换(也就是他不编码的那些字符,他也不解码),而dencodeURIComponent函数会解码它不编码的字符。
补充: encodeURIComponent和PHP的urlencode并不能互相解码, 实际上, 客户端和服务器端没有必要互为编码解码, 它们独自运行就可以. 上面说了, encodeURI和encodeURIComponent主要是为了连接post和get数据. 当然我们知道, 一般的网页数据请求内部都是自动转码的, 但是这个一般不用我们管, 包括中文, 在连接post,get数据的时候 转码并不是必须的, 转码的目的是把&=转掉, 免得服务器解析$_POST,$_GET的时候出现不希望的数据.
所以:
1. 虽然我们发送的数据是encode过的, 但是服务端的$_POST,$_GET的数据是不需要解码的, 因为它已经自动解好了.
2. 服务器输出字符的时候, 也是无需用urlencode转码的, 因为客户端在接收的时候也已经自动转好了. 如果多此一举的在服务器端用urlencode把数据编码, 用JavaScript是没有现成的函数来解码的, 硬要用decodeURIComponent解码, 虽然大多数时候是正确的, 但是个别字符会出现错误, 比如空格会被搞成+号.
表单有一个encripy选项, 它的默认值是application/x-www-form-urlencoded(ajax也有这个选项), 也就是对内容进行urlencode编码, JavaScript里并没有这个编码函数, 它实际上就是PHP的urlencode函数. 而数据被传到服务端的时候, _GET或_POST都已经自己解码.