Array.from
Najpierw próbuje wywołać iterator argumentu, jeśli ma jeden, a łańcuchy mają iteratory, więc wywołuje String.prototype[Symbol.iterator]
, więc sprawdźmy, jak działa metoda prototypowa. Jest to opisane w specyfikacji tutaj :
- Niech O będzie? RequireObjectCoercible (ta wartość).
- Bądźmy ? ToString (O).
- Zwróć CreateStringIterator (S).
Wyszukiwanie w CreateStringIterator
końcu prowadzi do tego 21.1.5.2.1 %StringIteratorPrototype%.next ( )
, co:
- Niech cp będzie! CodePointAt (s, position).
- Niech resultString będzie wartością String zawierającą cp. [[CodeUnitCount]] kolejne jednostki kodu od s zaczynające się od jednostki kodu w pozycji indeksu.
- Ustaw O. [[StringNextIndex]] na pozycję + cp. [[CodeUnitCount]].
- Zwróć CreateIterResultObject (resultString, false).
To, CodeUnitCount
co Cię interesuje. Numer ten pochodzi z CodePointAt :
- Niech najpierw będzie jednostką kodu w pozycji indeksu w ciągu.
- Niech cp będzie punktem kodowym, którego wartością liczbową jest wartość pierwsza.
Jeśli pierwszy nie jest wiodącym zastępczym lub końcowym zastępczym, wówczas
za. Zwróć rekord { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }
.
Jeśli pierwszy jest zastępczym zastępcą lub pozycją + 1 = rozmiar, to
a. Zwróć rekord { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }
.
Niech druga będzie jednostką kodu w pozycji indeksu + 1 w ciągu.
Jeśli drugi nie jest końcowym surogatem, to
za. Zwróć rekord { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }
.
Ustaw cp na! UTF16DecodeSurrogatePair (pierwszy, drugi).
Zwróć rekord { [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }
.
Tak więc, podczas iteracji po ciągu z Array.from
, zwraca CodeUnitCount 2 tylko wtedy, gdy dany znak jest początkiem pary zastępczej. Znaki interpretowane jako pary zastępcze opisano tutaj :
Takie operacje stosują specjalne traktowanie do każdej jednostki kodu o wartości liczbowej w zakresie od 0xD800 do 0xDBFF (zdefiniowanej w standardzie Unicode jako wiodący surogat , lub bardziej formalnie jako jednostka surogatu) i każdej jednostce kodu o wartości liczbowej w zakresie od 0xDC00 do 0xDFFF (zdefiniowanym jako zastępcze zastępcze, lub bardziej formalnie jako jednostka kodu o niskiej zastępczej), stosując następujące reguły ..:
षि
nie jest parą zastępczą:
console.log('षि'.charCodeAt()); // First character code: 2359, or 0x937
console.log('षि'.charCodeAt(1)); // Second character code: 2367, or 0x93F
Ale 👍
bohaterami są:
console.log('👍'.charCodeAt()); // 55357, or 0xD83D
console.log('👍'.charCodeAt(1)); // 56397, or 0xDC4D
Pierwszym kodem znakowym '👍'
jest szesnastkowy kod D83D, który należy do 0xD800 to 0xDBFF
wiodących zastępców. W przeciwieństwie do tego, pierwszy kod znakowy 'षि'
jest znacznie niższy i nie jest. Więc 'षि'
dzieli się, ale '👍'
nie robi.
षि
składa się z dwóch oddzielnych postaci: ष
, Devanagari List Ssa , a ि
, Devanagari samogłoska Zaloguj I . Gdy są obok siebie w tej kolejności, graficznie łączą się w jedną postać, mimo że składają się z dwóch osobnych postaci.
Natomiast kody znaków mają sens 👍
tylko wtedy, gdy są razem jako pojedynczy glif. Jeśli spróbujesz użyć łańcucha z jednym punktem kodowym bez drugiego, otrzymasz symbol nonsensowny:
console.log('👍'[0]);
console.log('👍'[1]);