我知道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链接吗?
答案 0 :(得分:2)
escape()
在B.2.1.2 escape部分中定义,并且introduction text of Annex B说:
...本附件中指定的所有语言功能和行为均具有一个或多个不良特征,在没有遗留用法的情况下,将从本规范中删除。 ...
对于代码单位值为0xFF或更小的字符,escape()
产生两位数字的转义序列:%xx
。这基本上意味着escape()
使用 latin-1 编码将仅包含字符从U+0000
到U+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 = "!" / "$" / "'" / "(" / ")" / "*"
/ "+" / "," / ";" / ":" / "@"
unreserved
和pct-encoded
在STD66中定义:
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
中的 val
或 example.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"