更换javascript转义?

时间:2014-10-13 14:14:40

标签: javascript encoding escaping mailto

我知道escape函数已被弃用,您应该使用encodeURI或encodeURIComponent。但是,encodeUri和encodeUriComponent与escape不同。

我想在javascript中使用瑞典语åäö创建mailto链接。以下是escape,encodeURIComponent和encodeURI:

之间的比较
console.log("mailto:?subject="+escape(subject)+"&body=" + escape(body));
console.log("mailto:?subject="+encodeURIComponent(subject)+"&body=" + encodeURIComponent(body));
console.log("mailto:?subject="+encodeURI(subject)+"&body=" + encodeURI(body));  

Output:
mailto:?subject=My%20subject%20with%20%E5%E4%F6&body=My%20body%20with%20more%20characters%20and%20swedish%20%E5%E4%F6
mailto:?subject=My%20subject%20with%20%C3%A5%C3%A4%C3%B6&body=My%20body%20with%20more%20characters%20and%20swedish%20%C3%A5%C3%A4%C3%B6
mailto:?subject=My%20subject%20with%20%C3%A5%C3%A4%C3%B6&body=My%20body%20with%20more%20characters%20and%20swedish%20%C3%A5%C3%A4%C3%B6 

只有使用“转义”创建的mailto链接才能使用IE或Chrome在Outlook中打开格式正确的邮件。当使用encodeURI或encodeURIComponent时,主题说:

My subject with åäö

并且身体也看起来很乱。

除了escape之外还有其他一些功能可以用来获取工作的mailto链接吗?

3 个答案:

答案 0 :(得分:2)

escape()B.2.1.2 escape部分中定义,并且introduction text of Annex B说:

  

...本附件中指定的所有语言功能和行为均具有一个或多个不良特征,在没有遗留用法的情况下,将从本规范中删除。 ...

对于代码单位值为0xFF或更小的字符,escape()产生两位数字的转义序列:%xx。这基本上意味着escape()使用 latin-1 编码将仅包含字符从U+0000U+00FF的字符串转换为百分比编码的字符串。

对于具有更大代码单位的字符,将使用四位数格式%uxxxx。在hfields-URI(在RFC6068中定义)的mailto:部分(存储主题和正文的区域)中不允许这样做:

mailtoURI    = "mailto:" [ to ] [ hfields ]
to           = addr-spec *("," addr-spec )
hfields      = "?" hfield *( "&" hfield )
hfield       = hfname "=" hfvalue
hfname       = *qchar
hfvalue      = *qchar
...
qchar        = unreserved / pct-encoded / some-delims
some-delims  = "!" / "$" / "'" / "(" / ")" / "*"
               / "+" / "," / ";" / ":" / "@"

unreservedpct-encodedSTD66中定义:

unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG

仅当百分号后接两个十六进制数字时才允许使用百分号,不允许百分号后接u

使用自我实现的版本,其行为类似于escape并不能解决任何问题-而是继续使用escape,不会很快将其删除。



总结一下:如果所有字符都在escape()U+0000范围内,则您先前使用U+00FF会生成拉丁语编码的mailto-URI,否则将生成无效的URI(如果考虑到javascript-encode / decode兼容性,则某些应用程序可能仍可以正确解释它们。

使用encodeURIComponent()(不要使用encodeURI()来生成UTF8百分比编码的mailto-URI是更正确的方法(没有创建无效URI的风险),并且是面向未来的。转义?/,...)。 RFC6068需要在许多地方使用UTF-8(但允许“ MIME编码的单词和组合电子邮件中的正文”使用其他编码)。

示例:

text_latin1="Swedish åäö"
text_other="Emoji "

document.getElementById('escape-latin-1-link').href="mailto:?subject="+escape(text_latin1);
document.getElementById('escape-other-chars-link').href="mailto:?subject="+escape(text_other);
document.getElementById('utf8-link').href="mailto:?subject="+encodeURIComponent(text_latin1);
document.getElementById('utf8-other-chars-link').href="mailto:?subject="+encodeURIComponent(text_other);

function mime_word(text){
  q_encoded = encodeURIComponent(text) //to utf8 percent encoded
  .replace(/[_!'()*]/g, function(c){return '%'+c.charCodeAt(0).toString(16).toUpperCase();})// encode some more chars as utf8
  .replace(/%20/g,'_') // mime Q-encoding is using underscore as space
  .replace(/%/g,'='); //mime Q-encoding uses equal instead of percent
  return encodeURIComponent('=?utf-8?Q?'+q_encoded+'?=');//add mime word stuff and escape for uri
}

//don't use mime_word for body!!!
document.getElementById('mime-word-link').href="mailto:?subject="+mime_word(text_latin1);
document.getElementById('mime-word-other-chars-link').href="mailto:?subject="+mime_word(text_other);
<a id="escape-latin-1-link">escape()-latin1</a><br/>
<a id="escape-other-chars-link">escape()-emoji</a><br/>
<a id="utf8-link">utf8</a><br/>
<a id="utf8-other-chars-link">utf8-emoji</a><br/>
<a id="mime-word-link">mime-word</a><br/>
<a id="mime-word-other-chars-link">mime-word-emoji</a><br/>

对我来说,UTF-8链接和Mime-Word链接在Thunderbird中有效。在Windows 10内置Mailapp和我的最新版本的Outlook中,仅普通的UTF-8链接有效。

答案 1 :(得分:0)

直接引用 MDN Documentation...

<块引用>

这个函数主要用于 URL 查询(URL 后面的部分?)——而不是用于转义普通字符串文字,使用格式“\xHH”。 (HH 是两个十六进制数字,形式 \xHH\xHH 用于高层 Unicode 字符。)

您遇到的问题是因为 escape() 不支持 UTF-8,而 encodeURI()encodeURIComponent() 支持。

但要绝对清楚从不使用encodeURI()encodeURIComponent()让我们试试看:

console.log(encodeURIComponent('@#*'));

输入:@#*。输出:%40%23*。通常,一旦用户输入被清除,我觉得我可以信任被清除的输入。但是,如果我在 Linux 系统上运行 rm * 来删除用户指定的文件,那实际上会删除我系统上的所有文件,即使我 100% 完全在服务器端进行了编码。这是 encodeURI()encodeURIComponent() 中的一个巨大错误,MDN Web 文档明确指出了解决方案。

在尝试对完整 URL(即所有 example.com?arg=val)进行编码时使用 fixedEncodeURI(),如 MDN encodeURI() Documentation...

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

或者,您可能需要使用 fixedEncodeURIComponent(),在尝试对 URL 的一部分进行编码时(即 arg 中的 valexample.com?arg=val),如在 MDN encodeURIComponent() Documentation...

中定义和进一步解释 <块引用>
function fixedEncodeURIComponent(str) {
 return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
   return '%' + c.charCodeAt(0).toString(16);
 });
}

如果您无法区分 fixedEncodeURI()fixedEncodeURIComponent()escape() 的作用,我总是喜欢将其简化为:

  • fixedEncodeURI()不会+@?=:#;,$& 编码为其 http 编码的等价物(如 &+是常见的网址运算符)
  • fixedEncodeURIComponent() +@?=:#;,$& 编码为其 http 编码的等效项。

答案 2 :(得分:-3)

在JavaScript 1.5版中不推荐使用escape()函数。请改用encodeURI()encodeURIComponent()

示例

string:            "May/June 2016, Volume 72, Issue 3"
escape:            "May/June%202016%2C%20Volume%2072%2C%20Issue%203"
encodeURI:         "May/June%202016,%20Volume%2072,%20Issue%203"
encodeURIComponent:"May%2FJune%202016%2C%20Volume%2072%2C%20Issue%203"

来源https://www.w3schools.com/jsref/jsref_escape.asp