繁体   English   中英

在 JavaScript 中对 utf-8 字符串使用 encodeURI() 与 escape()

[英]Using encodeURI() vs. escape() for utf-8 strings in JavaScript

我在 JavaScript 中处理 utf-8 字符串,需要对它们进行转义。

escape() / unescape() 和 encodeURI() / decodeURI() 都在我的浏览器中工作。

逃脱()

> var hello = "안녕하세요"
> var hello_escaped = escape(hello)
> hello_escaped
  "%uC548%uB155%uD558%uC138%uC694"
> var hello_unescaped = unescape(hello_escaped)
> hello_unescaped
  "안녕하세요"

编码URI()

> var hello = "안녕하세요"    
> var hello_encoded = encodeURI(hello)
> hello_encoded
  "%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94"
> var hello_decoded = decodeURI(hello_encoded)
> hello_decoded
  "안녕하세요"

但是, Mozilla 表示不推荐使用 escape()

尽管 encodeURI() 和 decodeURI() 使用上述 utf-8 字符串,但文档(以及函数名称本身)告诉我这些方法用于 URI; 我没有看到任何地方提到的 utf-8 字符串。

简单地说,utf-8 字符串可以使用 encodeURI() 和 decodeURI() 吗?

你好!

当谈到escapeunescape ,我遵循两条规则:

  1. 尽可能避免它们。
  2. 否则,请使用它们。

当您可以轻松地避免它们时:

正如问题中提到的, escapeunescape都已被弃用。 一般来说,应该避免使用不推荐使用的函数。

所以,如果encodeURIComponentencodeURI对你有用,你应该使用它而不是escape

当您无法轻松避免它们时使用它们:

浏览器将尽可能努力实现向后兼容。 所有主流浏览器都已经实现了escapeunescape 他们为什么要取消实施它们?

如果新规范要求浏览器重新定义escapeunescape ,他们将不得不这样做。 可是等等! 编写规范的人非常聪明。 他们也有兴趣不破坏向后兼容性!

我意识到上述论点是薄弱的。 但是请相信我,......当涉及到浏览器时,不推荐使用的东西是有效的。 这甚至包括不推荐使用的 HTML 标签,例如<xmp><center>

使用escapeunescape

那么自然地,下一个问题是,什么时候使用escapeunescape

最近,在处理CloudBrave 时,我不得不处理utf8latin1和相互转换。

在阅读了一堆博客文章后,我意识到这是多么简单:

var utf8_to_latin1 = function (s) {
    return unescape(encodeURIComponent(s));
};
var latin1_to_utf8 = function (s) {
    return decodeURIComponent(escape(s));
};

这些不使用escapeunescape相互转换相当复杂。 通过不避免escapeunescape ,生活变得更简单。

希望这可以帮助。

Mozilla 说不推荐使用 escape() 。

是的,你应该避免同时使用escape()unescape()


简单地说,utf-8 字符串可以使用 encodeURI() 和 decodeURI() 吗?

是的,但根据您输入的形式和所需的输出形式,您可能需要一些额外的工作。

根据您的问题,我假设您有一个 JavaScript 字符串,并且您想将编码转换为 UTF-8,并最终以某种转义形式存储该字符串。

首先需要注意的是,JavaScript 字符串编码是 UCS-2,类似于 UTF-16,不同于 UTF-8。

请参阅: https : //mathiasbynens.be/notes/javascript-encoding

encodeURIComponent()非常适合这项工作,因为它将 UCS-2 JavaScript 字符串转换为 UTF-8,并以%nn子字符串序列的形式对其进行转义,其中每个nn是每个字节的两个十六进制数字。

但是encodeURIComponent()不会转义 ASCII 范围内的字母、数字和其他一些字符。 但这很容易解决。

例如,如果要将 JavaScript 字符串转换为表示原始字符串 UTF-8 编码的字节的数字数组,则可以使用此函数:

//
// Convert JavaScript UCS2 string to array of bytes representing the string UTF8 encoded
//

function StringUTF8AsBytesArrayFromString( s )
{
    var i,
        n,
        u;

    u = [];
    s = encodeURIComponent( s );

    n = s.length;
    for( i = 0; i < n; i++ )
    {
        if( s.charAt( i ) == '%' )
        {
            u.push( parseInt( s.substring( i + 1, i + 3 ), 16 ) );
            i += 2;
        }
        else
        {
            u.push( s.charCodeAt( i ) );
        }
    }

    return u;
}

如果要将字符串转换为十六进制表示:

//
// Convert JavaScript UCS2 string to hex string representing the bytes of the string UTF8 encoded
//

function StringUTF8AsHexFromString( s )
{
    var u,
        i,
        n,
        s;

    u = StringUTF8AsBytesArrayFromString( s );
    n = u.length;
    s = '';    

    for( i = 0; i < n; i++ )
    {
        s += ( u[ i ] < 16 ? '0' : '' ) + u[ i ].toString( 16 );
    }

    return s;
}

如果将 for 循环中的行更改为

s += '%' + ( u[ i ] < 16 ? '0' : '' ) + u[ i ].toString( 16 );

(在每个十六进制数字前添加%符号)

可以使用decodeURIComponent()将生成的转义字符串(UTF-8 编码)转回 JavaScript UCS-2 字符串

永远不能使用encodeURI()encodeURIComponent() 让我们试试看:

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

输入: @#* 输出: %40%23* 等等,那么, *字符到底发生了什么? 怎么没转化? 想象一下:您询问用户要删除哪个文件,他们的回答是* 服务器端,您使用encodeURIComponent()转换它,然后运行rm * 好吧,有消息告诉您:使用encodeURIComponent()意味着您刚刚删除了所有文件。

使用fixedEncodeURI() ,当尝试编码完整的 URL(即所有example.com?arg=val )时,如MDN encodeURI() 文档中定义和进一步解释的那样......

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

或者,您可能需要使用fixedEncodeURIComponent() ,当尝试编码 URL 的一部分(即example.com?arg=valargval )时,如MDN encodeURIComponent() 文档中定义和进一步解释的那样...

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

如果根据上面的描述你无法区分它们,我总是喜欢将其简化为:

  • fixedEncodeURI()不会将+@?=:#;,$&编码为其 http 编码的等价物(因为&+是常见的 URL 运算符)
  • fixedEncodeURIComponent()会将+@?=:#;,$&编码为它们的 http 编码等价物。

暂无
暂无

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

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