Array.fromNajpierw 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 CreateStringIteratorkoń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, CodeUnitCountco 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 0xDBFFwiodą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]);