javascript中charcode的Unicode字符用于charcodes>;0xFFFF

javascript中charcode的Unicode字符用于charcodes>;0xFFFF,javascript,unicode,astral-plane,Javascript,Unicode,Astral Plane,我需要从unicode字符码中获取字符串/字符,最后将其放入DOM TextNode中,以便使用客户端JavaScript将其添加到HTML页面中 目前,我正在做: String.fromCharCode(parseInt(charcode, 16)); 其中,charcode是包含charcode的十六进制字符串,例如“1D400”。应返回的unicode字符是字符串。fromCharCode只能处理BMP中的代码点(即最多U+FFFF)。要处理更高的代码点,可以使用中的此函数返回代理项对表

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

目前,我正在做:

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

其中,
charcode
是包含charcode的十六进制字符串,例如
“1D400”
。应返回的unicode字符是
字符串。fromCharCode只能处理BMP中的代码点(即最多U+FFFF)。要处理更高的代码点,可以使用中的此函数返回代理项对表示:

function fixedFromCharCode (codePt) {
    if (codePt > 0xFFFF) {
        codePt -= 0x10000;
        return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
    } else {
        return String.fromCharCode(codePt);
    }
}

问题在于JavaScript中的字符是,但可以将JavaScript中基本多语言平面之外的字符表示为UTF-16代理项对

以下功能改编自:

功能utf16Encode(输入){
变量输出=[],i=0,len=input.length,value;
而(我0xFFFF){
值-=0x10000;
output.push(String.fromCharCode((值>>>10)和0x3FF)| 0xD800);
值=0xDC00 |(值&0x3FF);
}
push(String.fromCharCode(value));
}
返回output.join(“”);
}
警报(utf16Encode([0x1D400]);

EcmaScript语言规范第8.4节说

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

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

这篇文章很好地描述了如何做到这一点

UTF-16使用一个或两个无符号16位代码单元的序列对Unicode码点进行编码。值U+0000到U+FFFF以一个具有相同值的16位单位进行编码。补充字符以两个代码单元编码,第一个从高代理项范围(U+D800到U+DBFF),第二个从低代理项范围(U+DC00到U+DFFF)。这在概念上似乎与多字节编码相似,但有一个重要区别:U+D800到U+DFFF的值保留在UTF-16中使用;没有字符被指定为代码点。这意味着,对于字符串中的每个代码单元,软件可以判断它是表示一个单位字符,还是表示两个单位字符的第一个或第二个单位。这是对一些传统多字节字符编码的重大改进,其中字节值0x41可能表示字母“a”或是两字节字符的第二个字节

下表显示了几个字符的不同表示形式:

代码点/UTF-16代码单元

U+0041/0041

U+00DF/00DF

U+6771/6771

U+10400/D801 DC00

了解UTF-16代码单元后,可以使用javascript函数
string创建字符串。fromCharCode

String.fromCharCode(0xd801, 0xdc00) === '
String.fromCodePoint()
seems to do the trick as well. See here.

console.log(String.fromCodePoint(0x1D622, 0x1D623, 0x1D624, 0x1D400));
String.fromCharCode(0xd801,0xdc00)=='
String.fromCodePoint()
似乎也能做到这一点。看

输出:


所以JScript字符串是UTF-16编码的,据我所知,这段代码是charcode=>UTF-16转换。。。我希望问题(和解决方案)是这样的。成功了!坦克!我尝试了这个,得到了一个“字符转换错误”-但我意识到脚本文件是用utf-8编码的;当我将编码更改为ucs2(notepad++)时,它起了作用。虽然我使用了(较短的)失范代码,但我接受了您的解决方案,因为您的代码进行了很好的错误检查(但我不需要它)。请注意,正确的术语只是
UTF-16
编码。这会将前65536个字符(代理项除外)的一对一映射到
UCS-2
。但是从你的代码中我们可以看到,它只是“普通的”
UTF-16
@AlexisWilke:不完全是。JavaScript字符不是以UCS-2或UTF-16的形式公开的:它与UCS-2完全相同,只是允许使用代理。它不是UTF-16,因为不匹配的代理和错误顺序的代理是允许的。只有在浏览器中呈现字符时,UTF-16样式的代理才会组合成单个Unicode字符。这里有一篇很好的背景文章:感谢您的详细解释!这使我更深入地理解了JScript字符串的行为。w3schools的以下文档中对fromCharCode的描述似乎是错误的,因为它只是说“Unicode值”,但0x1A000也是一个“Unicode值”:@leems,因为我引用了规范:“15.5.3.2 String.fromCharCode([char0[,char1[,…]))返回一个字符串值,该值包含的字符数与参数数相同。每个参数指定结果字符串的一个字符,第一个参数从左到右指定第一个字符,依此类推。通过应用操作ToUint16(9.7)将参数转换为字符并将得到的16位整数视为字符的代码单位值。如果未提供任何参数,则结果为空字符串。“@leems,因为字符是UTF-16代码单位,而ToUint16(0x10000)==0,尝试将补充代码单位传递给
字符串。fromCharCode
将无法按预期工作。不幸的是,
String.fromCharCode(0x10000)='\u0000'
。内博斯加·西里奇和其他人正在努力使下一个版本在i18n方面变得更好:我说的“错”是指对i18n的描述
String.fromCharCode(0xd801, 0xdc00) === '
String.fromCodePoint()
seems to do the trick as well. See here.

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