【问题标题】:How can I construct a UTF-16 character in JavaScript from the surrogate pair?如何从代理对构造 JavaScript 中的 UTF-16 字符?
【发布时间】:2020-02-20 16:49:04
【问题描述】:

以下计算 Unicode 代码点 (Face with Medical Mask) 的 UTF-16 代理项对。

但是我怎样才能从代理对构造字符,以便在字符串中使用?

const codepoint = 0b11111011000110111 // ????
const tmp = codepoint - 0x10000
const padded = tmp.toString(2).padStart(20, '0')
const unit1 = (Number.parseInt(padded.substr(0, 10), 2) + 0xD800).toString(16)
const unit2 = (Number.parseInt(padded.substr(10), 2) + 0xDC00).toString(16)

// obviously hard-coding the values works...
console.log(`Hard-coded: \ud83d\ude37`)
// ...but how to combine unit1 and unit2 to print the character?
console.log(`Dynamic: unit1: ${unit1}, unit2: ${unit2}`)

【问题讨论】:

  • 我更新了我的答案。我从办公桌前走开,想起 fromCharCode 接受多个代码单元,因此无需调用两次。

标签: javascript unicode


【解决方案1】:

给你两个答案:

您可能不必

在现代 JavaScript 环境中,您不必将代码点分开,您可以使用 String.fromCodePoint 直接创建字符:

const ch = String.fromCodePoint(codepoint);

现场示例:

const codepoint = 0b11111011000110111; // ?
const ch = String.fromCodePoint(codepoint);

console.log(ch);

您可以从零件构建它

如果您没有fromCodePoint 或者您有代理项作为起点,您可以通过fromCharCode 获取每个代理项的字符串版本——但不要使用toString(16),将单位保留为数字:

const unit1 = Number.parseInt(padded.substr(0, 10), 2) + 0xD800;
const unit2 = Number.parseInt(padded.substr(10), 2) + 0xDC00;

const ch = String.fromCharCode(unit1, unit2);

现场示例:

const codepoint = 0b11111011000110111 // ?
const tmp = codepoint - 0x10000
const padded = tmp.toString(2).padStart(20, '0')
const unit1 = Number.parseInt(padded.substr(0, 10), 2) + 0xD800;
const unit2 = Number.parseInt(padded.substr(10), 2) + 0xDC00;

const ch = String.fromCharCode(unit1, unit2);

console.log(ch);

你甚至可以这样做

const ch = String.fromCharCode(unit1) + String.fromCharCode(unit2);

...但是由于fromCharCode 接受多个字符代码(代码单元),因此将它们同时传递给它可能更有意义。

它可以单独使用每个 (String.fromCharCode(unit1) + String.fromCharCode(unit2)) 的事实可能看起来非常非常奇怪。 “你的意思是 String.fromCharCode 很高兴地创建了一个只有 一半 代理对的字符串?!”是的。 :-) JavaScript 字符串是 UTF-16 代码单元的序列它们容忍无效或孤立的代理对。来自the spec

String 类型是由零个或多个 16 位无符号整数值(“元素”)组成的所有有序序列的集合,最大长度为 253 - 1 个元素。 String 类型通常用于表示正在运行的 ECMAScript 程序中的文本数据,在这种情况下,String 中的每个元素都被视为 UTF-16 代码单元值。 ...

不解释字符串内容的 ECMAScript 操作不应用进一步的语义。解释字符串值的操作将每个元素视为单个 UTF-16 代码单元。 但是,ECMAScript 不限制这些代码单元的值或之间的关系,因此将字符串内容进一步解释为以 UTF-16 编码的 Unicode 代码点序列的操作必须考虑格式错误的子序列。 ...

(我的重点)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    相关资源
    最近更新 更多