Normalize: примеры (JAVASCRIPT)
normalize(form?): stringОсновные сведения о функции normalize
Метод normalize() принадлежит объекту String в JavaScript. Его основное назначение — приведение строки к одной из стандартных форм нормализации Юникода (Unicode). Нормализация используется для обеспечения единообразного представления текста, состоящего из символов, которые могут быть записаны различными способами (например, с использованием комбинирующихся диакритических знаков).
Функция вызывается для строки и принимает один необязательный аргумент — форму нормализации:
- form (необязательный) — строка, указывающая форму нормализации. Допустимые значения:
'NFC','NFD','NFKC','NFKD'. Если аргумент опущен или равенundefined, используется'NFC'.
Возвращаемое значение — новая строка, представляющая нормализованную форму исходной строки согласно указанной форме. Если значение аргумента form не является допустимым, генерируется исключение RangeError.
Описание форм нормализации:
- NFC (Normalization Form Canonical Composition) — каноническая композиция. Символы по возможности представляются в виде единых составных символов (например, 'é' как один символ). Это форма по умолчанию.
- NFD (Normalization Form Canonical Decomposition) — каноническая декомпозиция. Символы раскладываются на базовые символы и комбинирующиеся знаки (например, 'é' на 'e' и комбинирующийся acute accent).
- NFKC (Normalization Form Compatibility Composition) — совместимая композиция. Сначала применяется декомпозиция совместимости, затем каноническая композиция. Эта форма заменяет совместимые символы (например, лигатуры, стилистические варианты) их эквивалентами.
- NFKD (Normalization Form Compatibility Decomposition) — совместимая декомпозиция. Применяется декомпозиция совместимости, при которой совместимые символы заменяются.
Использование функции актуально при сравнении строк, сортировке, поиске, хранении текста, а также при работе с текстом на разных языках, содержащим диакритические знаки.
Простыe случаи применения
Пример с различными формами нормализации для символа с диакритическим знаком:
let str = 'café';
// Символ 'é' может быть представлен как U+00E9 или как U+0065 + U+0301
console.log(str.normalize('NFC')); // 'café' (композиция)
console.log(str.normalize('NFD')); // 'café' (декомпозиция - базовый символ и комбинирующийся знак)'café' 'café'
Пример с совместимыми символами (римская цифра):
let roman = 'Ⅳ'; // Римская цифра 4 (один символ)
console.log(roman.normalize('NFKC')); // Заменяется на 'IV'
console.log(roman.normalize('NFKD')); // Также 'IV''IV' 'IV'
Пример с опущенным аргументом:
let word = 'naïve';
console.log(word.normalize()); // Используется NFC по умолчанию'naïve'
Аналогичные функции в JavaScript
Прямых аналогов функции normalize() в JavaScript нет, так как ее задача специфична. Однако для некоторых смежных задач могут применяться другие методы.
- String.prototype.localeCompare() — выполняет сравнение строк с учетом языка и региональных настроек. Может учитывать особенности символов, но не выполняет нормализацию. Используется для корректной сортировки строк.
- Intl.Collator — объект, предоставляющий более гибкое сравнение строк с учетом локали. Позволяет задавать чувствительность к регистру, диакритическим знакам и другим параметрам. Нормализацию не производит, но может работать с уже нормализованными строками для повышения точности сравнения.
В случаях, когда требуется именно приведение к канонической форме Юникода, используется только normalize(). Для сравнения строк, которые могут иметь разное представление символов, предварительная нормализация и последующее сравнение (например, через === или localeCompare) является предпочтительным подходом.
Распространенные ошибки
1. Передача недопустимого значения формы нормализации. Генерируется исключение RangeError.
try {
'text'.normalize('INVALID');
} catch (e) {
console.log(e.name + ': ' + e.message);
}RangeError: The normalization form should be one of NFC, NFD, NFKC, NFKD.
2. Предположение, что нормализация изменяет исходную строку. Метод возвращает новую строку, исходная остается неизменной.
let original = 'café';
let normalized = original.normalize('NFD');
console.log(original); // 'café'
console.log(normalized); // 'café''café' 'café'
3. Использование нормализации для всех задач сравнения строк без учета локали. Для сортировки или сравнения с учетом правил языка требуется localeCompare или Intl.Collator даже после нормализации.
let a = 'café';
let b = 'café'; // Разное представление
console.log(a === b); // false
console.log(a.normalize('NFC') === b.normalize('NFC')); // truefalse true
История изменений
Метод normalize() был добавлен в стандарт ECMAScript 6 (ES2015). С момента внедрения спецификация функции не претерпевала значительных изменений в основных браузерах и средах выполнения JavaScript.
Важные моменты:
- Функция стала частью языка с ES6. До этого требовались сторонние библиотеки для нормализации.
- Поведение и поддерживаемые формы нормализации соответствуют стандарту Unicode. Актуальные версии JavaScript следуют последним версиям стандарта Unicode, что может влиять на обработку некоторых символов в новых версиях движков.
- Поддержка функции в старых браузерах (например, Internet Explorer) отсутствует или может быть неполной. Для совместимости может потребоваться использование полифилов.
Рекомендуется проверять поддержку в целевых средах выполнения, если важна работа с устаревшими системами.
Расширенные примеры использования
Пример 1: Нормализация перед сравнением строк для поиска.
let searchTerm = 'café'.normalize('NFC'); // Приводим к единой форме
let items = ['café', 'cafe', 'coffee'];
let results = items.filter(item => item.normalize('NFC') === searchTerm);
console.log(results); // ['café']['café']
Пример 2: Подсчет символов с учетом нормализации. Без нормализации символ, представленный двумя кодовыми точками (например, 'e' + комбинирующийся знак), будет считаться за два символа.
let str = 'café'; // 'e' + U+0301
console.log(str.length); // 5
console.log(str.normalize('NFC').length); // 4 (символ 'é' как один)5 4
Пример 3: Удаление диакритических знаков через нормализацию NFD и фильтрацию.
function removeDiacritics(str) {
return str.normalize('NFD')
.replace(/[\u0300-\u036f]/g, ''); // Удаляем комбинирующиеся диакритические знаки
}
console.log(removeDiacritics('cliché')); // 'cliche'
console.log(removeDiacritics('naïve')); // 'naive''cliche' 'naive'
Пример 4: Работа с эмодзи и специальными символами. Некоторые эмодзи состоят из нескольких кодовых точек, и нормализация может на них влиять.
let emoji = '❤️';
console.log(emoji.normalize('NFD').length); // Может отличаться в зависимости от представления2
Пример 5: Использование NFKC для приведения текста к совместимой форме, что полезно для идентификаторов или URL.
let text = '¹²³'; // Надстрочные цифры
console.log(text.normalize('NFKC')); // '123' (обычные цифры)'123'
Нормализация в других языках программирования
Концепция нормализации Юникода присутствует во многих языках программирования, часто в составе библиотек для работы с Unicode.
Python (модуль unicodedata):
import unicodedata
str = 'café'
print(unicodedata.normalize('NFC', str)) # 'café'
print(unicodedata.normalize('NFD', str)) # 'café'café café
PHP (класс Normalizer):
$str = 'café';
echo Normalizer::normalize($str, Normalizer::FORM_C); // 'café'
echo Normalizer::normalize($str, Normalizer::FORM_D); // 'café'café café
Java (класс java.text.Normalizer):
String str = "café";
String nfc = Normalizer.normalize(str, Normalizer.Form.NFC); // "café"
String nfd = Normalizer.normalize(str, Normalizer.Form.NFD); // "café"café café
MySQL (функции NORMALIZE() и WF_NORMALIZE_STRING()): Нормализация доступна в некоторых контекстах, например, для полнотекстового поиска или сравнения. Конкретный синтаксис зависит от версии и настроек сервера.
Основное отличие реализации в JavaScript — это метод, встроенный в объект String, что делает его использование очень простым. В других языках обычно требуется импорт отдельного модуля или класса.