转自:http://blog.csdn.net/ljb2010_/archive/2010/12/13/6073507.aspx
在ajax开发中经常用到编码的情况,尤其是中文情况下。那么encodeURI,encodeComponent到底做了什么?为什么有encodeURI ,还有encodeURIComponent?
认识URI(Uniform Resource Identifier) 参考RFC3968 http://gbiv.com/protocols/uri/rfc/rfc3986.html
URI翻译作 统一资源标识符,暂理解为 资源的唯一表示,其中我们所熟悉的URL,以及URN都是其子集。关于URN参考http://www.ietf.org/rfc/rfc2141.txt ,这里不解释了,没接触过不太理解。
URI的语法组成
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
一个URI 会包含
scheme(如 http ,ftp 等,是由[BCP35]定义的),
authority [ userinfo "@" ] host [ ":" port ] 常见URL中的就只有一个host,前后都没有。需登陆的ftp带有@符号出现
path 路径
query 查询串,URL中经常有的 "?"后面部分 (可选)
fragment 锚点,URL中常有 "#"后面部分(可选)
这些部分都叫 URI的组件 (URIComponent),一个URI是由好多个URIComponent组成的,URIComponent之间有分割符,这些分割符由保留字符组成。理解了这些URIComponent,就好理解encodeURIComponent和encodeURI了。
foo://example.com:8042/over/there?name=ferret#nose
/_/ /______________//_________/ /_________/ /__/
| | | | |
scheme authority path query fragment
| _____________________|__
/ / / /
urn:example:animal:ferret:nose
例如ajax通讯的时候,资源的内容如下一个JSON格式 {url:http://www-zorder.cn?map=1&debug=1,name:"z-order"},用ajax_get 发起请求,如果不编码,则会出现GET的数据错误,因为&符号在webserver端接收的时候"&"是一个分隔符,并不代表数据,所以必须对这个JSON数据进行编码。这个时候应该用encodeURIComponent(), 因为这个JSON出现在query数据段,可以理解为GET请求时的URI中的 query 组件的一部分,所以应该选择 对URI组件编码 encodeURIComponent,encodeURIComponent将返回合法的URI组件。这里的合法,是指字符的合法,不包含保留字符。
URI中的保留字符有 " ? # [ ] @ ! $ & ' ( ) * + , ; = / ",(双引号中部分)。目前javascript中 encodeURIComponent会对保留字符中除了 " ! ( ) * ' " 以外的字符进行编码。
总结:
encodeURI() ,是对一个统一资源标识进行编码,比如常见的一个带中文的url连接,它会将保留字符识别为URI的分隔符,
encodeURIComponent() 是对URI组件进行编码,它将不识别URI中的保留字符为分隔符,而将其识别为数据,URI组件的组成部分,从而会对保留字符进行编码,或者可以理解为转义
两者的编码方式是一样的,编码后的数据 格式为: %HEX (e.t. %51%b6),其中的HEX为该字符的ASCII码的十六进制表示。对于utf8编码的中文,例如"中" => "%E4%B8%AD", utf8中文字占三个字节,编码后的值就是每个字节的十六进制值,服务器端脚本要decode也很容易。
比较
encodeURI 和 escape的区别,两者都是编码,有什么区别?
参考 Mozilla doc
http://developer.mozilla.org/En/Core_JavaScript_1.5_Guide/Predefined_Functions/Escape_and_unescape_Functions
the escape function returns the hexadecimal encoding of an argument in the ISO Latin character set.
escape编码是将传入的字符 编码成 拉丁字符集 并返回其十六进制表示。其实际上返回的是unicode UCS-2编码的十六进制值(%uxxxx, 0-127和ASCII编码相同%xx),而UCS-2编码采用两个字节,最多只能表示6万多个字符,显然这个在处理中文偏僻的字的时候会出错。所以在上面mozilla的doc中指出不推荐使用escape来编码,因为escape的编码字符集有限,推荐用encodeURIComponent来编码。
关于PHP对应的处理
php中对应的处理是这样子,php的中urldecode系列的方法可以处理encodeURI的结果。php 对于js中escape的编码,没有内置的方法支持,不过转换很简单,先将字符串中 /%u?/d+/ 匹配出来,然后pack一下,得到的是uc2编码的字符,如果输出的是utf8 或者gb2312 ,则需要经过转换再输出。
--------------------------------------------------------------------------------
w3school的解释:
http://www.w3school.com.cn/js/jsref_encodeURI.asp
http://www.w3school.com.cn/js/jsref_encodeURIComponent.asp
encodeURI和encodeURIComponent都不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
而对于:“;/?:@&=+$,#” 这些url中的分格符号,encodeURI不会进行编码,而encodeURIComponent会进行编码。