Skip to content

Commit 7e4f329

Browse files
authored
Merge pull request #1745 from Alexandre887/master
Юникод
2 parents 0ba846e + 696af00 commit 7e4f329

File tree

2 files changed

+178
-128
lines changed

2 files changed

+178
-128
lines changed

1-js/05-data-types/03-string/article.md

Lines changed: 5 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,8 @@ alert(str1 == str2); // true
8484
|`\\`|Обратный слеш|
8585
|`\t`|Знак табуляции|
8686
|`\b`, `\f`, `\v`| Backspace, Form Feed и Vertical Tab — оставлены для обратной совместимости, сейчас не используются. |
87-
|`\xXX`|Символ с шестнадцатеричным Юникодным кодом `XX`, например, `'\x7A'` — то же самое, что `'z'`.|
88-
|`\uXXXX`|Символ в кодировке UTF-16 с шестнадцатеричным кодом `XXXX`, например, `\u00A9` — Юникодное представление знака копирайта, `©`. Код должен состоять ровно из 4 шестнадцатеричных цифр. |
89-
|`\u{X…XXXXXX}` (от 1 до 6 шестнадцатеричных цифр)|Символ в кодировке UTF-32 с шестнадцатеричным кодом от U+0000 до U+10FFFF. Некоторые редкие символы кодируются двумя 16-битными словами и занимают 4 байта. Так можно вставлять символы с длинным кодом. |
9087

91-
Примеры с Юникодом:
92-
93-
```js run
94-
alert( "\u00A9" ); // ©
95-
alert( "\u{20331}" ); // 佫, редкий китайский иероглиф (длинный Юникод)
96-
alert( "\u{1F60D}" ); // 😍, символ улыбающегося лица (ещё один длинный Юникод)
97-
```
98-
99-
Все спецсимволы начинаются с обратного слеша, `\` — так называемого "символа экранирования".
88+
Как вы можете видеть, все спецсимволы начинаются с обратного слеша, `\` — так называемого "символа экранирования".
10089

10190
Он также используется, если необходимо вставить в строку кавычку.
10291

@@ -504,13 +493,6 @@ alert( "Wid*!*get*/!*".endsWith("get") ); // true, "get" — окончание
504493
alert( String.fromCodePoint(90) ); // Z
505494
```
506495

507-
Также можно добавлять Юникодные символы по их кодам, используя `\u` с шестнадцатеричным кодом символа:
508-
509-
```js run
510-
// 90 — 5a в шестнадцатеричной системе счисления
511-
alert( '\u005a' ); // Z
512-
```
513-
514496
Давайте сделаем строку, содержащую символы с кодами от `65` до `220` — это латиница и ещё некоторые распространённые символы:
515497

516498
```js run
@@ -557,118 +539,11 @@ alert( 'Österreich'.localeCompare('Zealand') ); // -1
557539
558540
У этого метода есть два дополнительных аргумента, которые указаны в [документации](mdn:js/String/localeCompare). Первый позволяет указать язык (по умолчанию берётся из окружения) — от него зависит порядок букв. Второй — определить дополнительные правила, такие как чувствительность к регистру, а также следует ли учитывать различия между `"a"` и `""`.
559541
560-
## Как всё устроено, Юникод
561-
562-
```warn header="Глубокое погружение в тему"
563-
Этот раздел более подробно описывает, как устроены строки. Такие знания пригодятся, если вы намерены работать с эмодзи, редкими математическими символами, иероглифами, либо с ещё какими-то редкими символами.
564-
565-
Если вы не планируете их поддерживать, эту секцию можно пропустить.
566-
```
567-
568-
### Суррогатные пары
569-
570-
Все часто используемые символы имеют 2-байтовые коды. Буквы в большинстве европейских языков, цифры и даже большинство иероглифов имеют 2-байтовое представление.
571-
572-
Но 2 байта допускают только 65536 комбинаций, так что на все символы этого, разумеется, не хватит. Поэтому редкие символы кодируются парой 2-байтовых символов, также называемые "суррогатной парой".
573-
574-
Длина таких символов равна `2`:
575-
576-
```js run
577-
alert( '𝒳'.length ); // 2, MATHEMATICAL SCRIPT CAPITAL X
578-
alert( '😂'.length ); // 2, FACE WITH TEARS OF JOY
579-
alert( '𩷶'.length ); // 2, редкий китайский иероглиф
580-
```
581-
582-
Обратите внимание, суррогатные пары не существовали, когда был создан JavaScript, поэтому язык не обрабатывает их адекватно!
583-
584-
Ведь в каждой из этих строк только один символ, а `length` показывает длину `2`.
585-
586-
`String.fromCodePoint` и `str.codePointAt` — два редких метода, правильно работающие с суррогатными парами, но они и появились в языке недавно. До них были только [String.fromCharCode](mdn:js/String/fromCharCode) и [str.charCodeAt](mdn:js/String/charCodeAt). Эти методы, вообще, делают то же самое, что `fromCodePoint/codePointAt`, но не работают с суррогатными парами.
587-
588-
Получить символ, представленный суррогатной парой, может быть не так просто, потому что суррогатная пара интерпретируется как два символа:
589-
590-
```js run
591-
alert( '𝒳'[0] ); // странные символы...
592-
alert( '𝒳'[1] ); // ...части суррогатной пары
593-
```
594-
595-
Части суррогатной пары не имеют смысла сами по себе, так что вызовы `alert` в этом примере покажут лишь мусор.
596-
597-
Технически, суррогатные пары возможно обнаружить по их кодам: если код символа находится в диапазоне `0xd800..0xdbff`, то это — первая часть суррогатной пары. Следующий символ — вторая часть — имеет код в диапазоне `0xdc00..0xdfff`. Эти два диапазона выделены исключительно для суррогатных пар по стандарту.
598-
599-
В данном случае:
600-
601-
```js run
602-
// charCodeAt не поддерживает суррогатные пары, поэтому возвращает код для их частей
603-
604-
alert( '𝒳'.charCodeAt(0).toString(16) ); // d835, между 0xd800 и 0xdbff
605-
alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3, между 0xdc00 и 0xdfff
606-
```
607-
608-
Дальше в главе <info:iterable> будут ещё способы работы с суррогатными парами. Для этого есть и специальные библиотеки, но нет достаточно широко известной, чтобы предложить её здесь.
609-
610-
### Диакритические знаки и нормализация
611-
612-
Во многих языках есть символы, состоящие из некоторого основного символа со знаком сверху или снизу.
613-
614-
Например, буква `a` — это основа для `àáâäãåā`. Наиболее используемые составные символы имеют свой собственный код в таблице UTF-16. Но не все, в силу большого количества комбинаций.
615-
616-
Чтобы поддерживать любые комбинации, UTF-16 позволяет использовать несколько Юникодных символов: основной и дальше один или несколько особых символов-знаков.
617-
618-
Например, если после `S` добавить специальный символ "точка сверху" (код `\u0307`), он отобразится как Ṡ.
619-
620-
```js run
621-
alert( 'S\u0307' ); //
622-
```
623-
624-
Если надо добавить сверху (или снизу) ещё один знак — без проблем, просто добавляем соответствующий символ.
625-
626-
Например, если добавить символ "точка снизу" (код `\u0323`), отобразится S с точками сверху и снизу: `Ṩ`.
627-
628-
Добавляем два символа:
629-
630-
```js run
631-
alert( 'S\u0307\u0323' ); // Ṩ
632-
```
633-
634-
Это даёт большую гибкость, но из-за того, что порядок дополнительных символов может быть различным, мы получаем проблему сравнения символов: можно представить по-разному символы, которые ничем визуально не отличаются.
635-
636-
Например:
637-
638-
```js run
639-
let s1 = 'S\u0307\u0323'; // Ṩ, S + точка сверху + точка снизу
640-
let s2 = 'S\u0323\u0307'; // Ṩ, S + точка снизу + точка сверху
641-
642-
alert( `s1: ${s1}, s2: ${s2}` );
643-
644-
alert( s1 == s2 ); // false, хотя на вид символы одинаковы (?!)
645-
```
646-
647-
Для решения этой проблемы есть алгоритм "Юникодной нормализации", приводящий каждую строку к единому "нормальному" виду.
648-
649-
Его реализует метод [str.normalize()](mdn:js/String/normalize).
650-
651-
```js run
652-
alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true
653-
```
654-
655-
Забавно, но в нашем случае `normalize()` "схлопывает" последовательность из трёх символов в один: `\u1e68` — S с двумя точками.
656-
657-
```js run
658-
alert( "S\u0307\u0323".normalize().length ); // 1
659-
660-
alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
661-
```
662-
663-
Разумеется, так происходит не всегда. Просто Ṩ — это достаточно часто используемый символ, поэтому создатели UTF-16 включили его в основную таблицу и присвоили ему код.
664-
665-
Подробнее о правилах нормализации и составлении символов можно прочитать в дополнении к стандарту Юникод: [Unicode Normalization Forms](http://www.unicode.org/reports/tr15/). Для большинства практических целей информации из этого раздела достаточно.
666-
667542
## Итого
668543
669544
- Есть три типа кавычек. Строки, использующие обратные кавычки, могут занимать более одной строки в коде и включать выражения `${…}`.
670545
- Строки в JavaScript кодируются в UTF-16.
671-
- Есть специальные символы, такие как `\n`, и можно добавить символ по его Юникодному коду, используя `\u…`.
546+
- Есть специальные символы, такие как разрыв строки `\n`.
672547
- Для получения символа используйте `[]`.
673548
- Для получения подстроки используйте `slice` или `substring`.
674549
- Для того, чтобы перевести строку в нижний или верхний регистр, используйте `toLowerCase/toUpperCase`.
@@ -681,4 +556,6 @@ alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true
681556
- `str.repeat(n)` — повторяет строку `n` раз.
682557
- …и другие, которые вы можете найти в [справочнике](mdn:js/String).
683558
684-
Также есть методы для поиска и замены с использованием регулярных выражений. Но это отдельная большая тема, поэтому ей посвящена отдельная глава учебника <info:regular-expressions>.
559+
Для строк предусмотрены методы для поиска и замены с использованием регулярных выражений. Но это отдельная большая тема, поэтому ей посвящена отдельная глава учебника <info:regular-expressions>.
560+
561+
Также, на данный момент важно знать, что строки основаны на кодировке Юникод, и поэтому иногда могут возникать проблемы со сравнениями. Подробнее о Юникоде в главе <info:unicode>.

0 commit comments

Comments
 (0)