【问题标题】:Convert Unicode characters to hex causes extra bytes将 Unicode 字符转换为十六进制会导致额外的字节
【发布时间】:2017-02-08 03:31:51
【问题描述】:

这是我用于转义多字节 unicode 字符的代码。

let sample = '1F3C4-1F3FB-200D-2640-FE0F'; //????????‍♀️
let characters = String.fromCodePoint(...sample.split('-').map(code => parseInt(code, 16)));
let codes = '';
for(let i=0;i<characters.length;i++){
    codes += (i === 0 ? '' : '-') + characters.codePointAt(i).toString(16).toUpperCase();
}
console.log(codes); //1F3C4-DFC4-1F3FB-DFFB-200D-2640-FE0F

从示例中可以看出,转换导致结果中增加了 2 个字节。

我的代码有什么问题吗?我该如何解决?

【问题讨论】:

  • 代码中的 str 应该改为 characters 吗?
  • @Frxstrem 我的错。我已经修好了。感谢您的提示。

标签: javascript unicode hex


【解决方案1】:

显然,codePointAt 函数给出了“一个表示给定索引处字符的代码单元值的数字”。但是,索引与charCodeAt 相同,因此如果该索引位于代理对的中间(例如\uD83C\uDFC4 用于\u{1F3C4}),它只会给出代理对的后半部分。

您可以在输出中看到这一点,因为额外的字符出现在两个具有代理对(U+1xxxx 字符)的字符之后,并且它们是前一个代理对的后半部分。

如果您使用的是 ES6,则可以使用扩展运算符来拆分 unicode 字符(而不像 <em>string</em>.split() 那样拆分代理对):

const string = "\u{1F3C4}\u{1F3FB}\u200D\u2640\uFE0F";
console.log(string); // ??‍♀️

const codes = [ ...string ].map(ch =>
  ch.codePointAt(0).toString(16).toUpperCase()
).join('-');
console.log(codes); // 1F3C4-1F3FB-200D-2640-FE0F

【讨论】:

  • 请问,为什么spread算子能正确分割代理对,而其他方法不能?
  • @Tresdin 因为 JavaScript 最近才添加了支持正确处理代理对的功能(例如 .codePointAt() 或扩展运算符); split() 和其他较旧的方法不支持它,因为向后兼容(例如,更改这些函数的行为破坏一些依赖它的应用程序)。这也是为什么有两个函数,codePointAtchatCodeAt,看似做同样的工作。
  • 我想我今天学到了一些新东西。非常感谢您的回答和奖金解释。
猜你喜欢
  • 2017-08-23
  • 2014-12-22
  • 2023-03-07
  • 2022-06-18
  • 2013-10-09
  • 1970-01-01
  • 2014-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多