Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork3
Unicode, String internals#213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
134 changes: 67 additions & 67 deletions1-js/99-js-misc/06-unicode/article.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,172 +1,172 @@ | ||
# Unicode,vnitřní reprezentace řetězce | ||
```warn header="Pokročilá znalost" | ||
Tato kapitola se hlouběji zabývá vnitřní reprezentací řetězců. Tato znalost vám bude užitečná, jestliže plánujete pracovat semoji,vzácnými matematickými nebo hieroglyfickými znaky nebo jinými vzácnými symboly. | ||
``` | ||
Jak už víme, řetězce v JavaScriptu jsou založeny na[Unicode](https://cs.wikipedia.org/wiki/Unicode):každý znak je reprezentován posloupností 1 až 4 bytů. | ||
JavaScriptnám umožňuje vložit znak do řetězce specifikací jeho hexadecimálního kódu vUnicodepomocí jednoho z následujících tří zápisů: | ||
- `\xXX` | ||
`XX`musí být dvě hexadecimální číslice s hodnotou mezi`00`a `FF`,pak `\xXX`je znak, jehož kód vUnicodeje `XX`. | ||
Protože zápis `\xXX`podporuje jen dvě hexadecimální číslice, může být použit jen pro prvních256znaků Unicode. | ||
Těchto prvních 256znaků obsahuje latinskou abecedu, většinu základních syntaktických znaků a některé další. Například`"\x7A"`je totéž jako `"z"` (Unicode `U+007A`). | ||
```js run | ||
alert( "\x7A" ); // z | ||
alert( "\xA9" ); // ©, symbol copyrightu | ||
``` | ||
- `\uXXXX` | ||
`XXXX` musí být přesně 4 hexadecimální číslice s hodnotou mezi `0000` a `FFFF`, pak `\uXXXX` je znak, jehož kód v Unicode je `XXXX`. | ||
Tímto zápisem mohou být reprezentovány i znaky, jejichž hodnoty v Unicode jsou větší než `U+FFFF`, ale v takovém případě musíme použít takzvaný zástupný pár (o zástupných párech pohovoříme později v této kapitole). | ||
```js run | ||
alert( "\u00A9" ); // ©,totéž jako\xA9 s použitím 4-ciferného hexadecimálního zápisu | ||
alert( "\u044F" ); // я,písmeno z kyrilice (azbuky) | ||
alert( "\u2191" ); // ↑,symbol šipky nahoru | ||
``` | ||
- `\u{X…XXXXXX}` | ||
`X…XXXXXX`musí být hexadecimální hodnota 1 až 6bytů mezi `0`a `10FFFF` (nejvyšší kódová hodnota definovaná vUnicode).Tento zápis nám umožňuje snadno reprezentovat všechny existující znaky v Unicode. | ||
```js run | ||
alert( "\u{20331}" ); // 佫,vzácný čínský znak (dlouhý Unicode) | ||
alert( "\u{1F60D}" ); // 😍,symbol usmívající se tváře (další dlouhý Unicode) | ||
``` | ||
##Zástupné páry | ||
Všechny často používané znaky mají 2-bytové kódy (4hexadecimální číslice).Písmena ve většině evropských jazyků, číslice a základní sjednocené ideografické sadyCJK (CJK --pro čínské, japonské a korejské písemné soustavy) mají 2-bytovou reprezentaci. | ||
JavaScriptbyl původně založen na kódováníUTF-16, které umožňovalo jen 2 byty na znak. Avšak 2byty umožňují jen 65536kombinací, a to pro každý možnýsymbolv Unicode nestačí. | ||
Vzácné symboly, které vyžadují více než 2 byty, jsou tedy zakódovány dvojicí 2-bytových znaků nazývanou „zástupný pár“ („surrogate pair“). | ||
Vedlejším efektem je, že délka takových symbolů je `2`: | ||
```js run | ||
alert( '𝒳'.length ); // 2,VELKÉ X V MATEMATICKÉM PÍSMU | ||
alert( '😂'.length ); // 2,TVÁŘ SE SLZAMI RADOSTI | ||
alert( '𩷶'.length ); // 2,vzácný čínský znak | ||
``` | ||
Je to proto, že v době, kdyJavaScriptvznikl, ještě zástupné páry neexistovaly, a proto nejsou jazykem správně zpracovávány! | ||
Ve skutečnosti máme v každém z uvedených řetězců jediný symbol, ale vlastnost `length`ukazuje délku `2`. | ||
Rovněž získání symbolu může být problematické, jelikož většina prvků jazyka zachází se zástupnými páry jako se dvěma znaky. | ||
Například zde vidíme na výstupu dva podivné znaky: | ||
```js run | ||
alert( '𝒳'[0] ); //zobrazuje zvláštní symboly... | ||
alert( '𝒳'[1] ); // ...části zástupného páru | ||
``` | ||
Části zástupného páru nemají jedna bez druhé žádný význam. V uvedeném příkladu se tedy ve skutečnosti zobrazí nesmysly. | ||
Technicky lze zástupné páry detekovat podle jejich kódu: jestliže znak má kód v intervalu`0xd800..0xdbff`,pak je to první část zástupného páru. Další znak (druhá část) musí mít kód v intervalu`0xdc00..0xdfff`.Tyto intervaly jsou ve standardu exkluzívně rezervovány pro zástupné páry. | ||
Proto byly do JavaScriptu přidány metody[String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)a [řetězec.codePointAt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt), které si dokáží se zástupnými páry poradit. | ||
Jsou v zásadě stejné jako[String.fromCharCode](mdn:js/String/fromCharCode)a [řetězec.charCodeAt](mdn:js/String/charCodeAt),ale se zástupnými páry zacházejí správně. | ||
Zde vidíme rozdíl: | ||
```js run | ||
// charCodeAt nezná zástupné páry, takže vydá kód pro 1. část: | ||
alert( '𝒳'.charCodeAt(0).toString(16) ); // d835 | ||
// codePointAtzná zástupné páry | ||
alert( '𝒳'.codePointAt(0).toString(16) ); // 1d4b3,přečte obě části zástupného páru | ||
``` | ||
Ovšem načítáme-li od pozice1 (a to je zde dosti nekorektní),pak obě vrátí jen druhou část páru: | ||
```js run | ||
alert( '𝒳'.charCodeAt(1).toString(16) ); // dcb3 | ||
alert( '𝒳'.codePointAt(1).toString(16) ); // dcb3 | ||
//nesmyslná 2. část páru | ||
``` | ||
Další způsoby, jak si se zástupnými páry poradit, naleznete v kapitole<info:iterable>.Pravděpodobně pro to existují i speciální knihovny, ale žádná není dostatečně známá na to, abychom ji tady doporučili. | ||
````warn header="Zásadní zjištění: dělení řetězců na libovolném místě je nebezpečné" | ||
Nemůžeme jen tak rozdělit řetězec na libovolné pozici, např. volat `řetězec.slice(0,6)`a očekávat, že tobude platný řetězec, např.: | ||
```js run | ||
alert( 'ahoj 😂'.slice(0,6) ); //ahoj [?] | ||
``` | ||
Zde vidíme na výstupu nesmyslný znak (první polovinu zástupného páru úsměvu). | ||
Mějte to na paměti, jestliže zamýšlíte zodpovědně pracovat se zástupnými páry. Nemusí to být velký problém, ale aspoň byste měli rozumět tomu, co se děje. | ||
```` | ||
##Diakritická znaménka a normalizace | ||
Mnoho jazyků obsahuje symboly, které se skládají ze základního znaku a znaménka nad nebo pod ním. | ||
Například písmeno`a`může být základním znakem pro tyto znaky: `àáâäãåā`. | ||
Většina běžných „složených“ znaků má v tabulce Unicode svůj vlastní kód. Ne však všechny, protože možných kombinací je příliš mnoho. | ||
Abychom mohli používat libovolné složeniny, standard Unicodenám umožňuje použít několik znakůUnicodeza sebou: základní znak následovaný jedním nebo více znaky „znamének“, která jej „ozdobí“. | ||
Například máme-li`S`následované speciálním znakem „tečka nahoře“ (kód `\u0307`),zobrazí se jako Ṡ. | ||
```js run | ||
alert( 'S\u0307' ); // Ṡ | ||
``` | ||
Potřebujeme-li další znaménko nad písmenem (nebo pod ním) --žádný problém, jednoduše přidáme potřebný znak znaménka. | ||
Například připojíme-li znak „tečka dole“ (kód `\u0323`),budeme mít „S s tečkami nahoře a dole“: `Ṩ`. | ||
Příklad: | ||
```js run | ||
alert( 'S\u0307\u0323' ); // Ṩ | ||
``` | ||
To nám poskytuje velkou flexibilitu, ale také zajímavý problém: dva znaky mohou vizuálně vypadat stejně, ale být reprezentovány různými složeninami z Unicode. | ||
Příklad: | ||
```js run | ||
let s1 = 'S\u0307\u0323'; // Ṩ, S +tečka nahoře +tečka dole | ||
let s2 = 'S\u0323\u0307'; // Ṩ, S +tečka dole +tečka nahoře | ||
alert( `s1: ${s1}, s2: ${s2}` ); | ||
alert( s1 == s2 ); // false, třebaže znaky vypadají stejně (?!) | ||
``` | ||
Řešení nám poskytuje algoritmus „normalizaceUnicode“, který převádí každý řetězec do jednoduché „normální“ formy. | ||
Je implementován metodou [řetězec.normalize()](mdn:js/String/normalize). | ||
```js run | ||
alert( "S\u0307\u0323".normalize() == "S\u0323\u0307".normalize() ); // true | ||
``` | ||
Je humorné, že v naší situaci `normalize()`ve skutečnosti spojí posloupnost tří znaků do jednoho: `\u1e68` (Sse dvěma tečkami). | ||
```js run | ||
alert( "S\u0307\u0323".normalize().length ); // 1 | ||
alert( "S\u0307\u0323".normalize() == "\u1e68" ); // true | ||
``` | ||
V realitě však tomu tak není vždy. Důvodem je, žesymbol `Ṩ`je „dostatečně běžný“, takže jej tvůrci Unicode zahrnuli do hlavní tabulky a přiřadili mu kód. | ||
Pokud se chcete o pravidlech a variantách normalizace dozvědět víc, jsou popsána v příloze standarduUnicode: [Normalizační formy Unicode](https://www.unicode.org/reports/tr15/),ale pro většinu praktických účelů je informace z tohoto článku dostačující. |
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.