题 你什么时候应该使用escape而不是encodeURI / encodeURIComponent?


编码要发送到Web服务器的查询字符串时 - 何时使用 escape() 你什么时候用的 encodeURI() 要么 encodeURIComponent()

使用转义:

escape("% +&=");

要么

使用encodeURI()/ encodeURIComponent()

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");

1285
2017-09-16 19:24


起源


值得指出的是 encodeURIComponent("var1=value1&var2=value2") 是 不 典型的用例。那个例子将编码 = 和 &,这可能不是预期的! encodeURIComponent 通常单独应用于每个键值对中的值(每个键值对后的部分) =)。 - Timothy Shields
你需要对钥匙做什么吗?如果它中有一个=怎么办? (那可能吗?) - Mala
@Mala我一般都是网络编程的新手,但我在有限的经验中使用的是分别对密钥和值进行编码,确保'='保持: var params = encodeURIComponent(key) + '=' + encodeURIComponent(value);  - 也许别人知道更好的方法。 - nedshares
@nedshares我正在玩那个,但据我所知,密钥似乎没有编码......至少不是以同样的方式。也许在密钥中有一个=是违反规范的? - Mala
还值得指出的是,最近的JavaScript实现提供了更高级别的接口 网址 和 URLSearchParams 用于操纵URL及其查询字符串。 - Bart Robinson


答案:


逃逸()

不要用它! escape() 在章节中定义 B.2.1.2逃脱 和 附件B的介绍文本 说:

...本附录中指定的所有语言特征和行为都具有一个或多个不良特征,并且在没有遗留用法的情况下将从本规范中删除。 ...
  ...编写新的ECMAScript代码时,程序员不应使用或假设存在这些特性和行为....

行为:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

特殊字符的编码除了:@ * _ + - ./

字符的十六进制形式,其代码单元值为0xFF或更小,是一个两位数的转义序列: %xx

对于具有更大代码单元的字符,采用四位数格式 %uxxxx 用来。查询字符串中不允许这样做(如 RFC3986):

query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

仅当百分号直接跟随两个十六进制数字,百分号后跟时,才允许百分号 u 不允许。

是encodeURI()

如果需要工作URL,请使用encodeURI。拨打这个电话:

encodeURI("http://www.example.org/a file with spaces.html")

要得到:

http://www.example.org/a%20file%20with%20spaces.html

不要调用encodeURIComponent,因为它会破坏URL并返回

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

encodeURIComponent方法()

如果要对URL参数的值进行编码,请使用encodeURIComponent。

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

然后,您可以创建所需的URL:

var url = "http://example.net/?param1=" + p1 + "&param2=99";

您将获得这个完整的URL:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

请注意,encodeURIComponent不会转义 ' 字符。一个常见的错误是使用它来创建html属性,如 href='MyUrl',这可能会遭受注射错误。如果要从字符串构造html,请使用 " 代替 ' 对于属性引号,或添加额外的编码层(' 可编码为%27)。

有关此类编码的更多信息,您可以检查: http://en.wikipedia.org/wiki/Percent-encoding


1816
2018-05-24 06:54



@Francois,取决于接收服务器,它可能无法正确解码转义编码高位ASCII或非ASCII字符的方式,例如:ầẩẫấậêềểễếệ例如,如果编译了bye escape,Python的FieldStorage类将无法正确解码上述字符串。 - Ray
@Francois escape()编码除字母,数字和*@-_+./之外的低128个ASCII字符,而unescape()是escape()的反转。据我所知,它们是为编码URL而设计的遗留功能,但仍然是为了向后兼容而实现的。通常,除非与为其设计的app / web服务/等交互,否则不应使用它们。 - Anthony DiSanti
当然,除非你试图将URL作为URI组件传递,在这种情况下调用encodeURIComponent。 - tom
为什么不处理单引号? - Eric
@Eric它不对单引号进行编码,因为单引号是在URI中发生的完全有效的字符(RFC-3986)。在HTML中嵌入URI时出现问题,其中单引号 不 一个有效的角色。接下来,URI也应该是“HTML编码的”(它将取代 ' 同 ')在放入HTML文档之前。 - Lee


和...之间的不同 encodeURI() 和 encodeURIComponent() 正好是由encodeURIComponent编码的11个字符,但不是由encodeURI编码的:

Table with the ten differences between encodeURI and encodeURIComponent

我很容易生成这个表 console.table 使用此代码在Google Chrome中:

var arr = [];
for(var i=0;i<256;i++) {
  var char=String.fromCharCode(i);
  if(encodeURI(char)!==encodeURIComponent(char)) {
    arr.push({
      character:char,
      encodeURI:encodeURI(char),
      encodeURIComponent:encodeURIComponent(char)
    });
  }
}
console.table(arr);


391
2017-10-09 09:26



+1表示清晰,另一个表示console.table魔法! - bladnman
这个浏览器不依赖吗? - Pacerier
@bladnman encodeURI和encodeURIComponent应该在所有主流浏览器中以这种方式工作。您可以在Chrome和Firefox中测试上述代码,因为它们都支持console.table。在其他浏览器(包括Firefox和Chrome)中,您可以使用以下代码: var arr=[]; for(var i=0;i<256;i++){var char=String.fromCharCode(i); if(encodeURI(char)!==encodeURIComponent(char)) console.log("character: "+char + " | encodeURI: " +encodeURI(char) + " |encodeURIComponent: " + encodeURIComponent(char) ) } - Johann Echavarria
我的意思是@Pacerier :) - Johann Echavarria
我需要对这几个时代进行推动!不幸的是只能投票一次。 - Ramazan Polat


我发现这篇文章很有启发性: Javascript疯狂:查询字符串解析

当我试图解释为什么decodeURIComponent没有正确解码'+'时,我找到了它。这是一个摘录:

String:                         "A + B"
Expected Query String Encoding: "A+%2B+B"
escape("A + B") =               "A%20+%20B"     Wrong!
encodeURI("A + B") =            "A%20+%20B"     Wrong!
encodeURIComponent("A + B") =   "A%20%2B%20B"   Acceptable, but strange

Encoded String:                 "A+%2B+B"
Expected Decoding:              "A + B"
unescape("A+%2B+B") =           "A+++B"       Wrong!
decodeURI("A+%2B+B") =          "A+++B"       Wrong!
decodeURIComponent("A+%2B+B") = "A+++B"       Wrong!

43
2018-05-08 07:51



你链接的文章包含很多废话。在我看来,作者本人并不明白这些功能是否适用于...... - Christoph
@Christoph这对我来说都很合理。特别是,我同意他的看法 encodeURI 看起来它只在一个相当模糊的边缘情况下才有用,而且确实不需要存在。我和他有一些不同意见,但我没有看到任何虚假或愚蠢的东西。你认为究竟是什么废话? - Mark Amery
该 enctype 的属性 FORM element指定用于对表单数据集进行编码以提交给服务器的内容类型。 应用程序/ x-WWW窗体-urlencoded    这是默认的内容类型。使用此内容类型提交的表单必须按如下方式编码:[...] 空格字符用“+”代替,[...]非字母数字字符用'%HH'代替,[...]  参考: HTML4 Sepc - cychoi
decodeURIComponent(“A +%2B + B”.replace(/ \ + / g,“”))=“A + B” - Nicholas
encodeURIComponent('A + B')。replace(/ \%20 / g,'+')+'\ n'+ decodeURIComponent(“A +%2B + B”.replace(/ \ + / g,'%20') )); - Zlatin Zlatev


encodeURIComponent不编码 -_.!~*'(),导致在xml字符串中将数据发布到php时出现问题。

例如:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

一般逃脱 encodeURI
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E

你可以看到,单引号没有编码。 要解决问题,我创建了两个函数来解决我的项目中的问题,对于编码URL:

function encodeData(s:String):String{
    return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}

对于解码URL:

function decodeData(s:String):String{
    try{
        return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
    }catch (e:Error) {
    }
    return "";
}

37
2017-09-16 19:26



它也没有#(磅/哈希/数字)符号,即%23。 - xr280xr


encodeURI() - escape()函数用于javascript转义,而不是HTTP。


36
2017-10-08 15:20



如果我有这样的网址: var url = "http://kuler-api.adobe.com/rss/get.cfm?startIndex=0&itemsPerPage=20&timeSpan=0&listType=rating"...我希望通过Google Ajax API访问它,如下所示: var gurl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;......然后我必须使用 escape(url)。 encodeURI(url) 不适用于看起来像这样的参数。 - Lance Pollard
你应该使用ecnodeURIComponent(url) - Ustaman Sangat
所有这3个功能都存在问题。最好创建自己的功能来完成工作。 - Jerry Joseph


小对比表Java与JavaScript对比PHP。

1. Java URLEncoder.encode (using UTF8 charset)
2. JavaScript encodeURIComponent
3. JavaScript escape
4. PHP urlencode
5. PHP rawurlencode

char   JAVA JavaScript --PHP---
[ ]     +    %20  %20  +    %20
[!]     %21  !    %21  %21  %21
[*]     *    *    *    %2A  %2A
[']     %27  '    %27  %27  %27 
[(]     %28  (    %28  %28  %28
[)]     %29  )    %29  %29  %29
[;]     %3B  %3B  %3B  %3B  %3B
[:]     %3A  %3A  %3A  %3A  %3A
[@]     %40  %40  @    %40  %40
[&]     %26  %26  %26  %26  %26
[=]     %3D  %3D  %3D  %3D  %3D
[+]     %2B  %2B  +    %2B  %2B
[$]     %24  %24  %24  %24  %24
[,]     %2C  %2C  %2C  %2C  %2C
[/]     %2F  %2F  /    %2F  %2F
[?]     %3F  %3F  %3F  %3F  %3F
[#]     %23  %23  %23  %23  %23
[[]     %5B  %5B  %5B  %5B  %5B
[]]     %5D  %5D  %5D  %5D  %5D
----------------------------------------
[~]     %7E  ~    %7E  %7E  ~
[-]     -    -    -    -    -
[_]     _    _    _    _    _
[%]     %25  %25  %25  %25  %25
[\]     %5C  %5C  %5C  %5C  %5C
----------------------------------------
char  -JAVA-  --JavaScript--  -----PHP------
[ä]   %C3%A4  %C3%A4  %E4     %C3%A4  %C3%A4
[ф]   %D1%84  %D1%84  %u0444  %D1%84  %D1%84

14
2017-09-16 19:40



类似的东西在这里: the-art-of-web.com/javascript/escape - Christophe Roussy
花花公子。你摇滚发布这个! - williamle8300


还要记住,它们都编码不同的字符集,并选择适当的字符集。 encodeURI()编码的字符数少于encodeURIComponent(),它比escape()编码的字符数更少(也与dannyp的点不同)。


10
2018-04-23 16:54





我建议不要使用其中一种方法。写出你自己的功能,做正确的事。

MDN给出了如下所示的url编码的一个很好的例子。

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName);

console.log(header); 
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"


function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            //  so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent


9
2018-04-21 07:55



多么好的答案(如果它兼容chrome edge和firefox而不会出错) - yan bellavance
这个答案值得更多的赞成。 - Adam