CodePointAt: примеры (JAVASCRIPT)
codePointAt(pos): numberОсновы функции codePointAt
Метод codePointAt() в JavaScript применяется к строке и возвращает неотрицательное целое число — код символа в кодировке Unicode (кодовую точку) для элемента строки по указанному индексу (позиции). Этот метод необходим для корректной работы с символами, выходящими за пределы Основной многоязычной плоскости (BMP), которые кодируются двумя 16-битными суррогатными парами (суррогатами) в UTF-16.
Метод используется при обработке текста, содержащего эмодзи, исторические письменности, математические символы или иные сложные символы, где charCodeAt() может дать некорректный результат, вернув только часть суррогатной пары.
Синтаксис: str.codePointAt(pos)
Параметры:
- pos (необязательный) — целое число, представляющее индекс элемента строки, для которого нужно получить кодовую точку. Если параметр не указан, по умолчанию используется 0. Если индекс выходит за пределы строки, метод возвращает
undefined.
Возвращаемое значение:
- Числовое значение кодовой точки Unicode для символа по указанному индексу.
undefined, если по указанному индексу нет элемента.
Короткие примеры использования
Базовое использование с символами из BMP (коды до 65535):
console.log('ABC'.codePointAt(1)); // Индекс 1 - символ 'B'
66
Использование с символами вне BMP (суррогатные пары):
let emoji = '????';
console.log(emoji.codePointAt(0)); // Эмодзи 'Ухмыляющееся лицо'
128512
Попытка получить код для второго суррогата пары:
console.log('????'.codePointAt(1)); // Второй суррогат эмодзи
56832
Обращение к несуществующему индексу:
console.log('Hi'.codePointAt(10));
undefined
Похожие функции в JavaScript
- charCodeAt(index) — возвращает числовое значение кодовой единицы UTF-16 (целое число от 0 до 65535). Для символов вне BMP возвращает значение только первого суррогата пары. Предпочтительнее использовать, если требуется обратная совместимость с очень старыми средами или работа строго в рамках BMP.
- String.fromCodePoint(...codePoints) — статический метод, создающий строку из последовательности кодовых точек Unicode. Является «полной» альтернативой для создания строк, в отличие от String.fromCharCode(), которая работает с кодовыми единицами. Используется вместе с codePointAt() для корректной обработки всех символов Unicode.
В современном коде для операций с символами, особенно при интернационализации, метод codePointAt() является предпочтительным выбором, так как он корректно обрабатывает всю область Unicode.
Типичные ошибки
1. Итерация по строке с помощью индекса и codePointAt() без учета суррогатных пар. Это приводит к некорректной обработке символов вне BMP, так как они занимают два индекса в строке JavaScript.
let str = 'Hi????';
for (let i = 0; i < str.length; i++) {
console.log(str.codePointAt(i));
}
72 (H) 105 (i) 128512 (????) 56832 (Второй суррогат пары, ошибочно выводится как отдельный символ)
2. Забывают, что индекс — это позиция в последовательности кодовых единиц UTF-16, а не видимых символов (графем).
console.log('????????????????'.length); // Семейный эмодзи состоит из нескольких символов-модификаторов
console.log('????????????????'.codePointAt(0)); // Возвращает код только для первого символа (мужчина)
11 128104
3. Сравнение строк по кодовым точкам без нормализации. Один и тот же символ может быть представлен разными кодовыми точками (например, с диакритическими знаками).
История изменений
Метод codePointAt() был добавлен в стандарт ECMAScript 6 (ES2015). До этого не существовало встроенного способа получения полной кодовой точки для символов вне Основной многоязычной плоскости. В более ранних версиях JavaScript для этих целей приходилось использовать сложные алгоритмы для обработки суррогатных пар вручную. С момента добавления спецификация метода не претерпевала существенных изменений.
Расширенные примеры
Корректная итерация по строке с учетом кодовых точек (символов, а не суррогатов):
let str = 'Hello????World????';
for (let i = 0; i < str.length; i++) {
let codePoint = str.codePointAt(i);
// Если кодовая точка больше 0xFFFF, это суррогатная пара, и нужно пропустить следующий индекс
if (codePoint > 0xFFFF) {
console.log(`Символ: ${String.fromCodePoint(codePoint)}, Код: ${codePoint}`);
i++; // Пропускаем второй суррогат
} else {
console.log(`Символ: ${str[i]}, Код: ${codePoint}`);
}
}
Символ: H, Код: 72 Символ: e, Код: 101 Символ: l, Код: 108 Символ: l, Код: 108 Символ: o, Код: 111 Символ: ????, Код: 128512 Символ: W, Код: 87 Символ: o, Код: 111 Символ: r, Код: 114 Символ: l, Код: 108 Символ: d, Код: 100 Символ: ????, Код: 127757
Использование для проверки, является ли символ суррогатной частью:
function isSurrogateAt(str, index) {
let code = str.charCodeAt(index);
return code >= 0xD800 && code <= 0xDFFF;
}
let testStr = '????';
console.log(isSurrogateAt(testStr, 0)); // true (первый суррогат)
console.log(isSurrogateAt(testStr, 1)); // true (второй суррогат)
console.log(testStr.codePointAt(0)); // 128512 (полный код)
true true 128512
Определение количества символов (не суррогатных единиц) в строке:
function countSymbols(str) {
let count = 0;
for (let i = 0; i < str.length; i++) {
let codePoint = str.codePointAt(i);
if (codePoint > 0xFFFF) i++; // Пропуск второго суррогата
count++;
}
return count;
}
console.log(countSymbols('a????b????c')); // 5
console.log('a????b????c'.length); // 8 (кодовых единиц UTF-16)
5 8
Аналоги функции в других языках
Python: Функция ord() возвращает код точки Unicode для строкового символа длиной в один символ. В отличие от JavaScript, она не работает по индексу строки.
print(ord('A')) # 65
print(ord('????')) # 128512
# print(ord('AB')) # Вызовет TypeError
65 128512
PHP: Функция IntlChar::ord() или mb_ord() (с расширением mbstring). mb_ord() принимает строку и возвращает кодовую точку Unicode первого символа.
echo mb_ord('A', 'UTF-8'); // 65
echo mb_ord('????', 'UTF-8'); // 128512
65 128512
C#: Свойство char.ConvertToUtf32(string, int) или метод Char.ConvertToUtf32(string, index) для получения кодовой точки с учетом суррогатных пар.
string str = "????";
int codePoint = Char.ConvertToUtf32(str, 0);
Console.WriteLine(codePoint); // 128512
128512