我可以依赖charCodeAt()和fromCharCode()的行为保持不变吗?

时间:2011-06-05 09:54:48

标签: javascript mysql perl unicode

我编写了一个个人网络应用,使用charCodeAt()将用户输入的文本转换为相关的字符代码(例如转换为8839进行存储)然后将其发送到Perl,后者将它们发送到MySQL。要检索输入文本,应用会使用fromCharCode()将数字转换回文本。

我选择这样做是因为Perl的unicode支持很难正确处理。所以Perl和MySQL只能看到数字,这会让生活变得更简单。

我的问题是,我可以依靠fromCharCode()始终将8834这样的数字转换为相关字符吗?我不知道它使用什么标准,但是假设它使用UTF-8,如果将来改为使用UTF-16,如果没有向后兼容性,这显然会破坏我的程序。

我知道我对这些概念的看法并不是那么清楚,因此请注意澄清我是否表现出误解。

6 个答案:

答案 0 :(得分:9)

假设所有字符都在基本多语言平面(BMP)中,

fromCharCodetoCharCode处理Unicode 代码点,即0到65535(0xffff)之间的数字。 Unicode和代码点是永久性的,因此您可以信任它们永远保持不变。

编码(如UTF-8和UTF-16)采用代码点(数字)流并输出字节流。 JavaScript有点奇怪,因为根据UTF-16规则,BMP之外的字符必须通过两次调用toCharCode来构造。但是,几乎你遇到的每一个角色(包括中文,日文等)都在BMP中,所以即使你不处理这些案件,你的程序也会有效。

您可以做的一件事是将数字转换回字节(以big-endian int16格式),并将结果文本解释为UTF-16。 fromCharCodetoCharCode的行为在当前的JavaScript实现中已得到修复,并且不会发生变化。

答案 1 :(得分:5)

  

我选择这样做是因为Perl的unicode支持很难正确处理。

这是真的!

Perl对任何主要编程语言都有最强大的Unicode支持。使用Perl比使用C,C ++ ,Java,C 更容易使用Unicode Python,Ruby,PHP或Javascript。这不是未受过教育的盲目忠诚的夸张和助推。基于十多年的专业经验和学习,这是一项经过深思熟虑的评估。

天真用户遇到的问题几乎总是因为他们欺骗了自己的Unicode。头号最糟糕的大脑错误认为Unicode就像ASCII,但更大。这绝对是完全错误的。正如我在别处写的那样:

  

从根本上和批判性不正确,Uɴɪᴄᴏᴅᴇ只是相对于ᴀsᴄɪɪ的一些放大字符集。至多,这只不过是stsᴏ-10646。 Uɴɪᴄᴏᴅᴇ包括更多,只是将字符分配给字形:校对和比较规则,三种形式的套管,非字母套管,多码点案例折叠,规范和兼容组合和分解归一化表单,序列化表单,字形集群,单词和换行符,脚本,数字等值,宽度,双向性,镜像,打印宽度,逻辑排序排除,字形变体,上下文行为,区域设置,正则表达式,多种形式的组合类,多个分解的类型,数百和数百非常有用的属性,以及更多!

是的,这很多,但它与Perl无关。它与Unicode有关。 Perl允许您在使用Unicode时访问这些内容不是错误而是功能。那些其他语言允许您完全访问Unicode绝不能被视为对他们有利的一点:相反,这些都是最严重的严重错误,因为如果你不能工作在21世纪使用Unicode,那么这种语言对于现代文本处理的苛刻要求来说是一种原始的,破碎的,根本无用的。

Perl不是。在Perl中使用这些东西比在其他语言中做这些事情要容易多了几百倍;在大多数人中,你甚至无法开始解决他们的设计缺陷。你只是简单地搞砸了。如果某种语言不能提供完整的Unicode支持,那么它就不适合本世纪;放弃它。

Perl使得Unicode比无法正常使用Unicode的语言更容易。

this answer中,您可以在前面找到用于在Perl中处理Unicode的七个简单步骤,在同一个答案的底部,您会发现一些有用的样板代码。理解它,然后使用它。不要接受破碎。您必须先学习Unicode才能使用Unicode。

这就是为什么没有简单的答案。 Perl使您可以轻松使用Unicode, 提供 ,您了解Unicode的真正含义。如果您正在处理外部源,那么您必须安排该源使用某种编码。

还阅读我所说的所有内容。那些是你真正需要理解的东西。另一个属于规则 49 的破坏问题是Javascript被破坏,因为它不会以完全相同的方式处理所有有效的Unicode代码点,而与其平面无关。 Javascript几乎在所有其他方面都被打破了。它不适合Unicode工作。只有规则 34 会杀了你,因为你无法让Javascript遵循things like \w中定义的Unicode regexes要求的标准}。

令人惊讶的是,有多少种语言对Unicode完全没用。但Perl绝对是其中之一!

答案 2 :(得分:4)

在我看来,不会突破。

阅读Joel Spolsky关于Unicode and character encoding的文章。本文的相关部分引用如下:

  

每一封信中都有   字母表分配了一个数字   这是一个Unicode联盟   写得像这样:U + 0639。这个   number被称为代码点。 U +   表示“Unicode”,数字是   十六进制。英文字母A会   是U + 0041。

这个神奇的数字是用utf-8还是utf-16或任何其他编码编码并不重要。这个数字仍然是一样的。

答案 3 :(得分:4)

正如其他答案中所指出的,fromCharCode()toCharCode()处理基本多语言平面(BMP)中任何代码点的Unicode代码点。 JavaScript中的字符串是UCS-2编码的,BMP外部的任何代码点都表示为两个JavaScript字符。这些都不会改变。

要处理JavaScript端的任何Unicode字符,您可以使用以下函数,该函数将返回表示指定字符串的Unicode代码点序列的数字数组:

var getStringCodePoints = (function() {
    function surrogatePairToCodePoint(charCode1, charCode2) {
        return ((charCode1 & 0x3FF) << 10) + (charCode2 & 0x3FF) + 0x10000;
    }

    // Read string in character by character and create an array of code points
    return function(str) {
        var codePoints = [], i = 0, charCode;
        while (i < str.length) {
            charCode = str.charCodeAt(i);
            if ((charCode & 0xF800) == 0xD800) {
                codePoints.push(surrogatePairToCodePoint(charCode, str.charCodeAt(++i)));
            } else {
                codePoints.push(charCode);
            }
            ++i;
        }
        return codePoints;
    }
})();

var str = "";
var codePoints = getStringCodePoints(s);

console.log(str.length); // 2
console.log(codePoints.length); // 1
console.log(codePoints[0].toString(16)); // 1d306

答案 4 :(得分:3)

JavaScript字符串是UTF-16,这不是要改变的东西。

但不要忘记UTF-16是可变长度编码。

答案 5 :(得分:0)

在2018年,您可以使用String.codePointAt()和String.fromCodePoint()。

即使角色不在基本多语言平面(BMP)中,这些方法也能正常工作。