Unicode代理对和String.fromCodePoint()— JavaScript

时间:2018-12-20 17:39:15

标签: javascript unicode hex unicode-escapes surrogate-pairs

我正在处理包含转义序列的原始字符串,以换取UTF星体符号的一半。 (我想我是正确的行话……)

console.log("\uD83D\uDCA9")
// => 

让我们以上面的表情符号为例。如果我有代理对(\ uD83D \ uDCA9),又该如何使用十六进制值并将其转换为Javascript String.fromCodePoint()函数的有效参数?

我尝试了以下操作:

const codePoint = ["D83D", "DCA9"].reduce((acc, cur) => {
    return acc += parseInt(cur, 16);
}, 0);

console.log(String.fromCodePoint(codePoint));
// =>  (some weird symbol appears, not !)

PS:我熟悉ES6转义序列,该序列显示括号{…}之间的十六进制值,而不是使用代理半部分。 但是我需要使用代理对!

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

您可以将值的列表传递给函数:

console.log(String.fromCodePoint(0xd83d, 0xdca9));

因此String.fromCodePoint()的“有效参数”不一定是单个值,实际上对于需要代理对的字符,根据定义 不能是单个值。为什么?因为就String.fromCodePoint()而言,每个单独的数字源值都必须是16位(2字节)的值。如果您可以传递更大的单个数字,则无需代理对!

修改:以上大部分内容都不正确; .fromCodePoint()方法 将接受完整的Unicode代码点值(大于16位)。当然,由于JavaScript字符串是UTF-16,它仍然必须将它们分成代理对,但这意味着如果您碰巧有完整的Unicode代码点,则不必自己将它们分开,这很好。但是,如果您已经了,那么对您自己进行组合实际上没有任何意义,因为当作为点列表的一部分传递时,该方法也可用于这些对。

如果数组中有值,则可以使用apply调用该函数:

var points = [0xd83d, 0xdca9];
console.log(String.fromCodePoint.apply(String, points));

答案 1 :(得分:2)

Pointy的解决方案是正确的,但是要回答您的问题,公式出了什么问题,问题在于您只需添加0xD83D和0xDCA9,得出0x1B4E6。但这不是代孕工作的方式。您应该使用正确的公式

( (first - 0xD800) << 10) + (second - 0xDC00) + 0x10000

可以缩写为

(first - 0xD7F7) << 10) + second

请参见Unicode encodings

如果这样做,您将得到0x1F4A9。

const codePoint = ["D83D", "DCA9"].reduce((acc, cur) => {
  cur = parseInt(cur, 16); return acc += cur<0xDC00 ? (cur-0xD7F7)<<10 : cur;
  }, 0);

console.log(String.fromCodePoint(codePoint));
// => now outputs !