给你两个答案:
您可能不必
在现代 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 代码点序列的操作必须考虑格式错误的子序列。 ...
(我的重点)