JS 中对URL传参包含特殊字符的处理

8,650 阅读4分钟

JS 中对URL传参包含特殊字符的处理

辛勤工作的一周又悄么声的过去,感觉一周马上过去了,应该干点啥,具体干点啥,嗯~~不敢问,不敢说,不敢想,啊哈,灵机一动,还是小结一篇文章表示曾经来过(这篇文章就在吃着川川的煎饼中英勇蛋生了!!!)。

本文由“十有八九”投稿,如有错误,欢迎指正。

声明文章参考一些博客,文章来源在文章末尾指出,如果遗漏,欢迎指出。

文章总结背景

在项目中很多时候会遇到URL中带有特殊字符的传参问题,后端接收到错误的参数信息,导致功能失败。

特殊字符的含义(十六进制):

符号 解释 转义
# 用来标志特定的文档位置 %23
% 对特殊字符进行编码 %25
& 分隔不同的变量值对 %26
+ 在变量值中表示空格 %2B
/ 表示目录路径 %2F
\ 表示目录路径 %5C
= 用来连接键和值 %3D
? 表示查询字符串的开始 %3F
空格 空格 %20
. 句号 %2E
: 冒号 %3A

针对上面提出的问题,普通的解决方法---正则替换解决,先来秀一波:

replace()方法替换匹配到的第一个字符串:str.replace('abc', 'Hello') replace()方法替换匹配到的所有字符串:str.replace(/abc/g, 'hello')

js中替换字符变量如下:

str=str.replace(/\%/g,"%25"); 
str=str.replace(/\#/g,"%23"); 
str=str.replace(/\&/g,"%26"); 
...

不但累成🐶,还没替换完,速度超级慢,还有遗漏的没替换???。。。

同事看到了你的这段代码转换,一脸懵逼,脑袋浮现一个词形容:“What?”,避免被吐槽,赶紧去复习总结了下各方法的区别,希望对读到这篇文章的你能有所帮助。

escape(str)方法

escape(str)方法生成新的由十六进制转义序列替换的字符串。

escape函数是全局对象的属性。该方法不会对ASCII字母和数字进行编码,其他所有的字符都会被转义序列替换,其中对中文编码使用Unicode字符集,下面特殊字符除外:@ * _ + - ./

字符的十六进制形式,其代码单元值为0xFF或更小,是一个两位数的转义序列:%xx。对于具有更大代码单元的字符,使用四位数格式%u xxxx。

代码示例如下:

escape('中文&hello@world') // %u4E2D%u6587%26hello@world
escape('abc123');        // abc123
escape('?');            // "%u0107"

\color{#FF8C00}{注:该特性已经从Web标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。}

encodeURI(URI)方法

该encodeURI()函数通过使用1到4个转义序列来表示每个字符的UTF-8编码来对统一资源标识符(URI)编码,(对于由两个字符组成的字符,用四个转义字符编码)。

假设有一个完整的URI,那么encodeURI不会编码那些对URI有特殊意义的字符。encodeURI不会编码以下特殊字符:**! @ # $& * ( ) = : / ; ? + ' **

encodeURIComponent(URI)方法

把URI字符串采用UTF-8编码格式转化成escape格式的字符串。与encodeURI()相比,这个方法将对更多的字符进行编码,如:反斜杠(‘/’);encodeURIComponent 转义除了字母、数字、(、)、.、!、~、*、'、-和_之外的所有字符。

注意:如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编码之后URL将显示错误。

代码示例如下:

encodeURIComponent("123-_.!~*'()abc")   // "123-_.!~*'()abc"
encodeURIComponent(";/?:@&=+$,#")  // "%3B%2F%3F%3A%40%26%3D%2B%24%2C%23"
encodeURIComponent("abc123")      // "abc123"
encodeURIComponent('中文&ABC/hello')  //"%E4%B8%AD%E6%96%87%26ABC%2Fhello"

encodeURIComponent是被使用最多的,它是将中文等特殊字符转换成utf-8格式的url编码。

encodeURI()和encodeURIComponent()的区别

举个栗子🌰来说明一下:

现在我要使用get方式将一个参数fromUrl,传递给服务器:

var  fromUrl="getList?id=1&name=zhangsan"; 
var  getURL="http://www.XXX.cn/test.php?form="+encodeURI(fromUrl);

这里,如果使用了encodeURI,那么最终的getURL的值为: 
"http://www.XXX.cn/test.php?form=getList?id=1&name=zhangsan"

这样,对参数fromUrl中的字符"&name=zhangsan",将不会作为字符串参数传递到服务器端,而是当作test.php的参数传递过去了,因为对"&name=zhangsan"中的字符"&"没有做编码。 
所以,在这种应用场景下,就需要使用encodeURIComponent,编码后的getURL值为: 
"http://www.XXX.cn/test.php?form=getList%3Fid%3D1%26name%3Dzhangsan"

方法总结

  1. escape()除了ASCII字母、数字和特定的符号外(@ * _ + - ./*),对传进来的字符串全部进行转义编码,因此如果想对URL编码,最好不要使用此方法。(该特性已经从Web标准中删除)
  2. encodeURI() 用于编码整个URI,因为URI中的合法字符都不会被编码转换
  3. encodeURIComponent()方法在编码单个URIComponent(指请求参数)应当是最常用的,它可以将参数中的中文、特殊字符进行转义,而不会影响整个URL。
  4. encodeURI()和encodeURIComponent()对中文的编码方式一样,一个中文3个十六进制的转义序列组成,默认编码字符集为UTF-8。

参考文章:

JAVASCRIPT中URL 传递参数(特殊字符)解决方法及转码解码的介绍

encode()

拓展:

ES5/标准 ECMAScript内置对象