Суррогатные пары Юникода и String.fromCodePoint () - JavaScript - PullRequest
0 голосов
/ 20 декабря 2018

Я имею дело с необработанными строками, содержащими escape-последовательности для суррогатных половинок астральных символов UTF.(Я думаю, что я правильно понял этот жаргон…)

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

Давайте использовать приведенные выше эмодзи в качестве примера.Если у меня есть суррогатная пара (\ uD83D \ uDCA9) Как я, в свою очередь, могу взять его шестнадцатеричные значения и превратить его в действительный аргумент для функции String.fromCodePoint() Javascript?

Я пробовал следующее:

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

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

PS: я знаком с escape-последовательностями ES6, которые показывают шестнадцатеричные значения в скобках {…} вместо использования суррогатных половинок. Но мне нужно сделать это с суррогатными парами!

Любые предложения приветствуются.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Решение от Pointy верное, но чтобы ответить на ваш вопрос, что не так с вашей формулой, проблема в том, что вы просто добавляете 0xD83D и 0xDCA9, в результате чего получается 0x1B4E6.Но суррогаты работают не так;Вы должны были использовать правильную формулу

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

, которую можно сократить до

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

См. Unicode-кодировки .

Если вы это сделаетевы получите 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 ?!
0 голосов
/ 20 декабря 2018

Вы можете передать список значений в функцию:

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

Таким образом, «действительный аргумент» для String.fromCodePoint() не обязательно является единственным значением, и действительно длясимвол, которому требуется суррогатная пара, по определению не может быть единственным значением.Зачем?Поскольку каждое отдельное числовое исходное значение, с точки зрения String.fromCodePoint(), должно быть 16-битным (2-байтовым) значением.Если бы вы могли передавать большие одиночные числа, в суррогатных парах не было бы необходимости!

Редактировать: большая часть вышеприведенного абзаца неточна;.fromCodePoint() метод будет принимать полные значения кодовой точки Unicode (больше 16 бит).Конечно, все равно приходится разбивать их на суррогатные пары, потому что строки JavaScript - это UTF-16, но это означает, что если у вас есть полноразмерные кодовые точки Unicode, вам не нужно разбивать их самостоятельно, что хорошо,Однако, если у вас do уже есть пары, на самом деле нет смысла объединять их самостоятельно, поскольку метод также работает с парами, когда они передаются как часть списка точек.

Если у вас есть значения вмассив, вы можете вызвать функцию с apply:

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