14

我需要从 unicode charcode 中获取字符串 / char,最后将其放入 DOM TextNode 以使用客户端 JavaScript 添加到 HTML 页面中。

目前,我正在做:

String.fromCharCode(parseInt(charcode, 16));

其中charcode是包含字符代码的十六进制字符串,例如"1D400". 应该返回的 unicode 字符是,但返回的是 a !按预期返回16 位范围 ( 0000... ) 中的字符。FFFF

有任何解释和/或更正建议吗?

提前致谢!

4

4 回答 4

20

String.fromCharCode 只能处理 BMP 中的代码点(即最多 U+FFFF)。为了处理更高的代码点,Mozilla Developer Network中的这个函数可用于返回代理对表示:

function fixedFromCharCode (codePt) {
    if (codePt > 0xFFFF) {
        codePt -= 0x10000;
        return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
    } else {
        return String.fromCharCode(codePt);
    }
}
于 2011-03-27T01:31:00.047 回答
15

问题是 JavaScript 中的字符(大部分)是 UCS-2 编码的,但可以将 JavaScript 中基本多语言平面之外的字符表示为 UTF-16 代理对。

以下函数改编自Converting punycode with dash character to Unicode

function utf16Encode(input) {
    var output = [], i = 0, len = input.length, value;
    while (i < len) {
        value = input[i++];
        if ( (value & 0xF800) === 0xD800 ) {
            throw new RangeError("UTF-16(encode): Illegal UTF-16 value");
        }
        if (value > 0xFFFF) {
            value -= 0x10000;
            output.push(String.fromCharCode(((value >>>10) & 0x3FF) | 0xD800));
            value = 0xDC00 | (value & 0x3FF);
        }
        output.push(String.fromCharCode(value));
    }
    return output.join("");
}

alert( utf16Encode([0x1D400]) );
于 2011-03-27T01:33:03.067 回答
9

EcmaScript 语言规范的第 8.4 节说

当一个字符串包含实际的文本数据时,每个元素都被认为是一个 UTF-16 代码单元。无论这是否是字符串的实际存储格式,字符串中的字符都按其初始代码单元元素位置编号,就好像它们使用 UTF-16 表示一样。对字符串的所有操作(除非另有说明)都将它们视为未区分的 16 位无符号整数序列;他们不确保生成的字符串是规范化的形式,也不确保语言敏感的结果。

因此,您需要将补充代码点编码为一对 UTF-16 代码单元。

文章“Java 平台中的补充字符”很好地描述了如何做到这一点。

UTF-16 使用一个或两个无符号 16 位代码单元的序列来编码 Unicode 代码点。值 U+0000 到 U+FFFF 以一个 16 位单元编码,具有相同的值。补充字符用两个代码单元编码,第一个来自高代理范围(U+D800 到 U+DBFF),第二个来自低代理范围(U+DC00 到 U+DFFF)。这在概念上似乎类似于多字节编码,但有一个重要区别:值 U+D800 到 U+DFFF 保留用于 UTF-16;没有字符被分配给它们作为代码点。这意味着,软件可以为字符串中的每个单独的代码单元判断它是否代表一个单元字符,或者它是双单元字符的第一个单元还是第二个单元。这是对一些传统的多字节字符编码的重大改进,

下表比较了几个字符的不同表示:

代码点/UTF-16 代码单元

U+0041 / 0041

U+00DF / 00DF

U+6771 / 6771

U+10400 / D801 DC00

一旦您知道 UTF-16 代码单元,您就可以使用 javascript 函数创建一个字符串String.fromCharCode

String.fromCharCode(0xd801, 0xdc00) === ''
于 2011-03-27T01:34:12.710 回答
1

String.fromCodePoint()似乎也可以解决问题。见这里

console.log(String.fromCodePoint(0x1D622, 0x1D623, 0x1D624, 0x1D400));

输出:


于 2019-03-17T12:42:00.700 回答