JavaScript之URL编码(二)

755 阅读4分钟

为什么要对URL编码?

根据网络标准RFC1738规定:URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。,如果URL上面出现了其他文字(比如中文),一定会对其编码。

URL是如何编码?

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>utf-8</title>
</head>
<body>
</body>
<script>
window.location.href="http://www.baidu.com?春节"
</script>
</html>

用a.html保存上面代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="gb2312">
    <meta name="viewport" content="width=device-width">
    <title>gb2312</title>
</head>
<body>
</body>
<script>
window.location.href="http://www.baidu.com?春节"
</script>
</html>

用b.html保存上面代码

编辑器的编码规则也需要用gb2312编码保存,否则会出现乱码!

然后用浏览器分别打开a.html和b.html,然后打开控制台,找到network,在All下面看到页面的请求,会发现a.html的请求是https://www.baidu.com/?%E6%98%A5%E8%8A%82,b.html的请求是https://www.baidu.com/?%B4%BA%BD%DA。

通过上面测试发现打开同一个页面会出现不同的编码规则是因为浏览器对URL的默认编码规则是按照页面的编码规则确定的也就是上面a.html(<meta charset="utf-8">)和b.html(<meta charset="gb2312">)。

通过我的上篇文章,用transfer(0x6625)函数可以得到"春"和"节"的utf-8编码分别是"E6 98 A5"和"E8 8A 82"。而"春"和"节"的gb2312编码分别是"B4 BA"和"BD DA"。

浏览器的规则:是将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。

不同的网页字符集,将导致完全不同的编码结果。有没有办法,能够保证客户端只用一种编码方法向服务器发出请求?答案就是使用Javascript先对URL编码,然后再向服务器提交,不要给浏览器插手的机会。

Javascript之URL编码

escape()

escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值。比如"春节"的返回结果是%u6625%u8282,也就是说在Unicode字符集中,"春"是第6625个(十六进制)字符,"节"是第8282个(十六进制)字符。

escape('春节')//%u6625%u8282
escape('春1aA节')//%u66251aA%u8282
escape('春@节')//%u6625@%u8282
'春'.charCodeAt().toString(16)//6625
'节'.charCodeAt().toString(16)//8282

它的具体规则是,除了ASCII字母、数字、标点符号"@ * _ + - . /"以外,对其他所有字符进行编码。在\u0000到\u00ff之间的符号被转成%xx的形式,其余符号被转成%uxxxx的形式。对应的解码函数是unescape()

unescape('%u6625%u8282')//春节
unescape('%u66251aA%u8282')//春1aA节
unescape('%u6625@%u8282')//春@节

encodeURI()

encodeURI()是Javascript中真正用来对URL编码的函数。

它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号"; / ? : @ & = + $ , #",也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%

encodeURI('春节')//"%E6%98%A5%E8%8A%82"
encodeURI('https://www.baidu.com/?春节')
//https://www.baidu.com/?%E6%98%A5%E8%8A%82这就是上面a.html的浏览器编码结果!

它对应的解码函数是decodeURI()。

decodeURI('%E6%98%A5%E8%8A%82')//春节

encodeURIComponent

最后一个Javascript编码函数是encodeURIComponent()。与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。

因此,"; / ? : @ & = + $ , #",这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码。至于具体的编码方法,两者是一样。

encodeURIComponent('春节')//%E6%98%A5%E8%8A%82
encodeURIComponent('春节=')//%E6%98%A5%E8%8A%82%3D,=被转码了

它对应的解码函数是decodeURIComponent()。

decodeURIComponent('%E6%98%A5%E8%8A%82%3D')//春节=

通过上面的学习,如果将b.html改成下面的格式,那么他就与a.html编码的结果一致。

<!DOCTYPE html>
<html>
<head>
    <meta charset="gb2312">
    <meta name="viewport" content="width=device-width">
    <title>utf-8</title>
</head>
<body>
</body>
<script>
var href=encodeURI('http://www.baidu.com?春节')
window.location.href=href;
</script>
</html>

<!DOCTYPE html>
<html>
<head>
    <meta charset="gb2312">
    <meta name="viewport" content="width=device-width">
    <title>utf-8</title>
</head>
<body>
</body>
<script>
var href=encodeURIComponent('春节')
window.location.href='http://www.baidu.com?'+href;
</script>
</html>

参考文章

关于RUL编码