繁体   English   中英

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

[英]When are you supposed to use escape instead of 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.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是不允许的。

编码URI()

当您需要工作 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

请注意,encodeURI 与 encodeURIComponent 一样,不会对 ' 字符进行转义。

编码URI组件()

当您想要对 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 编码而不是由 encodeURI 编码的 11 个字符:

包含 encodeURI 和 encodeURIComponent 之间的十个差异的表

我使用以下代码在谷歌浏览器中使用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: 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!

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 vs. JavaScript vs. 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/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

为了编码 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 的组件。 例如,需要附加一些用户输入示例 - encodeURIComponent('http://stackoverflow.com'); 会给 - http%3A%2F%2Fstackoverflow.com

所有这些编码都是在 UTF 8 中执行的,即字符将被转换为 UTF-8 格式。

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

还要记住,它们都对不同的字符集进行编码,并适当地选择您需要的字符集。 encodeURI() 编码的字符比 encodeURIComponent() 少,后者编码的字符比escape() 少(而且也不同于 dannyp 的观点)。

只需自己尝试encodeURI()encodeURIComponent() ......

 console.log(encodeURIComponent('@#$%^&*'));

输入: @#$%^&* 输出: %40%23%24%25%5E%26* 那么,等等, *发生了什么? 为什么这个没有转换? 如果您尝试执行linux command "$string"它肯定会导致问题。 TLDR:您实际上需要fixedEncodeURIComponent()fixedEncodeURI() 很长的故事...

何时使用encodeURI() 绝不。 encodeURI()在括号编码方面未能遵守 RFC3986。 使用fixedEncodeURI() ,如MDN encodeURI() 文档中定义和进一步解释的那样......

 function fixedEncodeURI(str) { return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']'); }

何时使用encodeURIComponent() 绝不。 encodeURIComponent()在编码方面未能遵守 RFC3986: !'()* 使用fixedEncodeURIComponent() ,如MDN encodeURIComponent() 文档中定义和进一步解释的那样......

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

然后您可以使用fixedEncodeURI()对单个 URL 片段进行编码,而fixedEncodeURIComponent()将对 URL 片段和连接器进行编码; 或者,简单地说, fixedEncodeURI()不会编码+@?=:#;,$& (因为&+是常见的 URL 运算符),但是fixedEncodeURIComponent()会。

我发现尝试各种方法是一个很好的健全性检查,即使在很好地掌握了它们的各种用途和功能之后也是如此。

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

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

接受的答案很好。 扩展最后一部分:

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

如果您想安全起见,也应该对未保留字符的百分比编码进行编码。

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

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

// fixedEncodeURIComponent("'") --> "%27"

Johann 桌子的启发,我决定扩展桌子。 我想看看哪些 ASCII 字符被编码。

console.table 的屏幕截图

 var ascii = " !\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; var encoded = []; ascii.split("").forEach(function (char) { var obj = { char }; if (char != encodeURI(char)) obj.encodeURI = encodeURI(char); if (char != encodeURIComponent(char)) obj.encodeURIComponent = encodeURIComponent(char); if (obj.encodeURI || obj.encodeURIComponent) encoded.push(obj); }); console.table(encoded);

表仅显示编码字符。 空单元格表示原始字符和编码字符相同。


只是为了额外,我为urlencode()rawurlencode()添加了另一个表。 唯一的区别似乎是空格字符的编码。

console.table 的屏幕截图

<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1);
$encoded = [];
foreach ($ascii as $char) {
    $obj = ["char" => $char];
    if ($char != urlencode($char))
        $obj["urlencode"] = urlencode($char);
    if ($char != rawurlencode($char))
        $obj["rawurlencode"] = rawurlencode($char);
    if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"]))
        $encoded[] = $obj;
}
echo "var encoded = " . json_encode($encoded) . ";";
?>
console.table(encoded);
</script>

@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 (以获得更漂亮的输出)。

我有这个功能...

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM