首页 文章

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

提问于
浏览
1314

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

使用转义:

escape("% +&=");

要么

使用encodeURI()/ encodeURIComponent()

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

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

13 回答

  • 1836

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

    Table with the ten differences between encodeURI and 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);
    
  • 11

    我有这个功能......

    var escapeURIparam = function(url) {
        if (encodeURIComponent) url = encodeURIComponent(url);
        else if (encodeURI) url = encodeURI(url);
        else url = escape(url);
        url = url.replace(/\+/g, '%2B'); // Force the replacement of "+"
        return url;
    };
    
  • 1

    我发现这篇文章很有启发性:Javascript Madness: Query String Parsing

    当我试图解释为什么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!
    
  • 37

    我发现即使在掌握了各种用途和功能之后,尝试各种方法也是一种很好的理智检查 .

    为此,我发现this website非常有用,以证实我怀疑我正在做一些适当的事情 . 它也被证明可用于解码encodeURIComponent的字符串,这对于解释起来相当具有挑战性 . 一个很棒的书签:

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

  • 1

    escape()

    不要用它! escape()B.2.1.2 escape部分中定义,introduction text of Annex 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

  • 403

    小对比表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
    
  • 43

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

    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

  • 3

    接受的答案是好的 . 扩展到最后一部分:

    请注意,encodeURIComponent不会转义'字符 . 一个常见的错误是使用它来创建html属性,例如href ='MyUrl',这可能会遭受注入错误 . 如果要从字符串构造html,可以使用“而不是”作为属性引号,或者添加额外的编码层('可以编码为%27) .

    如果你想要安全起见,percent encoding unreserved characters也应该被编码 .

    您可以使用此方法来转义它们(源Mozilla

    function fixedEncodeURIComponent(str) {
      return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
        return '%' + c.charCodeAt(0).toString(16);
      });
    }
    
    // fixedEncodeURIComponent("'") --> "%27"
    
  • 1

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

  • 16

    @ johann-echavarria的现代改写答案:

    console.log(
        Array(256)
            .fill()
            .map((ignore, i) => String.fromCharCode(i))
            .filter(
                (char) =>
                    encodeURI(char) !== encodeURIComponent(char)
                        ? {
                              character: char,
                              encodeURI: encodeURI(char),
                              encodeURIComponent: encodeURIComponent(char)
                          }
                        : false
            )
    )
    

    或者,如果您可以使用表格,请将 console.log 替换为 console.table (用于更漂亮的输出) .

  • 5

    出于编码的目的,javascript已经给出了三个内置函数 -

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

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

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

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

    encodeURIComponent differ from encodeURI in that it encode reserved characters and Number sign # of encodeURI

  • 37

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

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

相关问题