什么时候应该使用转义而不是 encodeURI / encodeURIComponent?

在对要发送到 Web 服务器的查询字符串进行编码时 - 什么时候使用escape()以及什么时候使用encodeURI()encodeURIComponent()

使用转义:

escape("% +&=");

要么

使用 encodeURI()/ encodeURIComponent()

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

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

答案

逃逸()

不要使用它! escape()B.2.1.2Escape 中定义,附件 B引言文本说:

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

行为:

https://developer.mozilla.org/zh-CN/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

encodeURI()encodeURIComponent()之间的区别恰好是由 encodeURIComponent 编码的 11 个字符,而不是由 encodeURI 编码的:

该表包含encodeURI和encodeURIComponent的十个区别

我使用以下代码通过 Google Chrome 中的console.table轻松生成了该表:

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);

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

我在尝试理解以下原因时发现了它,为什么为什么解码 URIComponent 无法正确解码 “+”。这是摘录:

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!

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 "";
}

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

小型对照表 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

我建议不要按原样使用这些方法之一。编写自己的函数,做正确的事。

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/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

还要记住,它们都编码不同的字符集,并适当选择所需的字符集。 encodeURI()编码的字符数少于 encodeURIComponent()的编码字符数,而 encodeURIComponent()的编码字符数少于(也不同于丹尼普的观点)编码的字符比 escape()少。

为了进行编码,javascript 提供了三个内置函数 -

  1. escape()- 不编码@*/+ ECMA 3 之后不推荐使用此方法,因此应避免使用。

  2. encodeURI()- 不对~!@#$&*()=:/,;?+'进行编码~!@#$&*()=:/,;?+'它假定 URI 是完整的 URI,因此不对 URI 中具有特殊含义的保留字符进行编码。当目的是转换完整的 URL 而不是 URL 的某些特殊段时,将使用此方法。示例encodeURI('http://stackoverflow.com');会给 - http: //stackoverflow.com

  3. encodeURIComponent() - _ . ! ~ * ' ( )不编码- _ . ! ~ * ' ( )此函数通过用表示该字符的 UTF-8 编码的一个,两个,三个或四个转义序列替换某些字符的每个实例来对统一资源标识符(URI)组件进行编码。此方法应用于转换 URL 的组成部分。例如,需要附加一些用户输入。示例encodeURI('http://stackoverflow.com');将给 - http%3A%2F%2Fstackoverflow.com

所有这些编码均以 UTF 8 执行,即字符将以 UTF-8 格式转换。

encodeURIComponent 与 encodeURI 的不同之处在于,它对保留字符和 encodeURI 的数字符号#进行编码

我发现即使对各种方法的各种用途和功能都有很好的了解,对各种方法进行试验也是一个很好的检查方法。

为此,我发现该网站对于确认我怀疑自己在做适当的事情非常有用。事实证明,它对于解码 encodeURIComponent 的字符串很有用,这可能很难解释。一个很棒的书签:

http://www.the-art-of-web.com/javascript/escape/