2016-07-13 9 views

Odpowiedz

9

JavaScript używa UTF-16 (source) zarządzać sznurki.

W UTF-16 jest 1 121 064 możliwe znaki. Teraz każda postać używa code points do reprezentacji (*). W UTF-16 jeden kod-punkt wykorzystuje dwa bajty (16 bitów) do zapisania. Oznacza to, że z jednym punktem kodowym możesz mieć różne znaki.

Oznacza to, że niektóre znaki muszą być reprezentowane za pomocą dwóch punktów kodowych.

String.length() zwraca liczbę jednostek kodu w łańcuchu, a nie liczbę znaków.

MDN wyjaśnia dość dobrze rzeczy na stronie o String.length()

Ta właściwość zwraca liczbę jednostek kod w ciąg. UTF-16, format ciągu używany przez JavaScript, używa pojedynczej 16-bitowej jednostki kodu do reprezentowania najczęściej występujących znaków, ale musi używać dwóch jednostek kodu dla rzadziej używanych znaków, więc możliwe jest, że wartość zwrócona przez długość do nie pasuje do faktycznej liczby znaków w ciągu.

(*): Właściwie kilka znaków, w zakresie 010000 - 03FFFF i 040000 - 10FFFF może używać maksymalnie 4 bajty (32 bity) na punkt kodowy, ale to nie zmienia odpowiedź : niektóre znaki wymagają więcej niż 2 bajtów do przedstawienia, więc potrzebują więcej niż 1 punktu kodowego.

Oznacza to, że niektóre znaki, które wymagają więcej niż 16 bitów, mają mimo wszystko długość 1. Jak 0x03FFFF, potrzebuje 21 bitów, ale wykorzystuje tylko jedną jednostkę kodu w UTF-16, więc jego String.length jest 1.

console.log(String.fromCharCode(0x03FFFF).length)

+0

Myślę, że tylko ES2015 używa UTF-16 zarówno wewnętrznie w silniku, jak i na poziomie języka.ES5 koduje UCT-2 (przynajmniej na poziomie języka). Poza tym istnieje tylko jeden punkt kodowy na znak (od 0x0 do 0x10FFFF), który jest reprezentowany przez jedną do dwóch jednostek kodu. Ponieważ 'string.length' interpretuje jednostki kodu jako pojedyncze znaki, oblicza błędne wyniki dla znaków spoza Basic Multilingual Plane (BMP). – ftor

+0

@ LUH3417 afaik ES5 również używa UTF-16: 'Gdy ciąg zawiera rzeczywiste dane tekstowe, każdy element jest uważany za pojedynczą jednostkę kodową UTF-16." Https://es5.github.io/ – rpadovani

+1

Och, mój błąd. Nazywa się to UCS-2, a silniki ES5 mogą używać dowolnego z nich (UCS-2/UTF-16). – ftor

5

wierzę rpadovani odpowiedział na to: „dlaczego "pytanie najlepiej, ale dla implementacji, która pozwoli uzyskać odpowiednią liczbę glifów w tej sytuacji, Lodash zajął się tym problemem w swoim module toArray.

Na przykład

_.toArray('12').length; // --> 3 

Albo, jeśli chcesz wbić kilka dowolne znaki poza ciągiem, manipulować i dołączyć tablicę, jak:

_.toArray("trimToEightGlyphs").splice(0,8).join(''); // --> 'trimToE' 
Powiązane problemy