Eu tenho brincado com o JS e não consigo descobrir como o JS decide quais elementos adicionar ao array criado ao usar Array.from()
. Por exemplo, o seguinte emoji 👍 tem um length
de 2, pois é composto por dois pontos de código, mas Array.from()
trata esses dois pontos de código como um, fornecendo uma matriz com um elemento:
const emoji = '👍';
console.log(Array.from(emoji)); // Output: ["👍"]
No entanto, alguns outros caracteres também têm dois pontos de código, como esse caractere षि
(também possui um .length
de 2). No entanto, Array.from
não "agrupa" esse personagem e produz dois elementos:
const str = 'षि';
console.log(Array.from(str)); // Output: ["ष", "ि"]
Minha pergunta é: O que determina se o caractere é dividido (como no exemplo dois) ou tratado como um único elemento (como no exemplo um) quando o caractere consiste em dois pontos de código?
javascript
string
unicode
iterator
Shnick
fonte
fonte
षि
é 2 caracteres separadoslength
. Iteradores ou mesmoSet
não funcionam com issoRespostas:
Array.from
primeiro tenta invocar o iterador do argumento, se ele tiver um, e as strings possuem iteradores, portanto, ele invocaString.prototype[Symbol.iterator]
, então vamos ver como o método prototype funciona. Está descrito na especificação aqui :Olhar para cima
CreateStringIterator
leva você a21.1.5.2.1 %StringIteratorPrototype%.next ( )
, o que faz:É nisso
CodeUnitCount
que você está interessado. Esse número vem do CodePointAt :Portanto, ao iterar sobre uma string com
Array.from
, ele retornará um CodeUnitCount de 2 somente quando o caractere em questão for o início de um par substituto. Caracteres que são interpretados como pares substitutos são descritos aqui :षि
não é um par substituto:Mas
👍
os personagens são:O primeiro código de caractere de
'👍'
é, em hexadecimal, D83D, que está dentro do intervalo0xD800 to 0xDBFF
dos principais substitutos. Por outro lado, o primeiro código de caractere de'षि'
é muito menor e não é. Então, isso'षि'
se divide, mas'👍'
não acontece.षि
é composto de dois caracteres separados:ष
, Devanagari Carta Ssa , eि
, Devanagari vogal Sinal I . Quando próximos um do outro nesta ordem, eles são combinados graficamente em um único caractere visualmente, apesar de serem compostos por dois caracteres separados.Por outro lado, os códigos de caracteres
👍
só fazem sentido quando juntos como um único glifo. Se você tentar usar uma string com um ponto de código sem o outro, receberá um símbolo sem sentido:fonte
षि
na verdade são dois caracteres com pontos de código distintos combinados para formar um único glifo (um caractere abstrato , como entendido pelos seres humanos). Isso contrasta com o👍
emoji, que é um caractere completo por si só, mesmo que seu ponto de código seja alto o suficiente para ser dividido em um par substituto. Acredito que esclarecer isso poderia ajudar muito (de outro modo, valioso) a responder.UTF-16 (a codificação usada para seqüências de caracteres em js) usa unidades de 16 bits. Portanto, todo unicode que pode ser representado usando 15 bits é representado como um ponto de código, e todo o resto como dois, conhecidos como pares substitutos . O iterador de strings itera sobre pontos de código.
UTF-16 na Wikipedia
fonte
É tudo sobre o código por trás dos personagens. Alguns são codificados em dois bytes (UTF-16) e são interpretados
Array.from
como dois caracteres. Preciso verificar a lista dos personagens:http://www.fileformat.info/info/charset/UTF-8/list.htm
http://www.fileformat.info/info/charset/UTF-16/list.htm
Para a função que exibe o código hexadecimal:
Javascript: string Unicode para hexadecimal
fonte