Inverter Texto: por que reverter uma string ingenuamente quebra emojis
A forma mais direta de inverter uma string em JavaScript —
texto.split("").reverse().join("") — opera sobre
unidades de código UTF-16, não sobre caracteres
visuais. Para texto ASCII e a maioria dos caracteres acentuados
latinos, isso não causa problema, porque cada caractere corresponde a
exatamente uma unidade de código. Mas para qualquer caractere fora do
Plano Multilíngue Básico do Unicode — a maioria dos emojis, por
exemplo — essa técnica quebra: um emoji representado por um par
substituto (surrogate pair, duas unidades de código UTF-16) tem essas
duas unidades invertidas de posição relativa, corrompendo o caractere
em dois pontos de código inválidos isolados, que navegadores
tipicamente exibem como um caractere de erro visível.
A técnica correta: iterar por ponto de código, não por unidade de código
A correção passa por Array.from(texto) em vez de
texto.split("") — Array.from() usa o
iterador padrão de string do JavaScript, que respeita pares
substitutos e trata cada ponto de código Unicode como um elemento
único, não cada unidade de código UTF-16 isoladamente. Essa é a mesma
técnica já usada em outras ferramentas deste site que processam
caractere a caractere — a página de Informações
de Caractere, por exemplo, usa exatamente Array.from()
para pegar corretamente "o primeiro caractere" de uma entrada, mesmo
quando esse caractere é um emoji de 4 bytes.
Inverter por palavra: uma operação diferente, sem essa armadilha
Inverter a ordem das palavras de uma frase (em vez de inverter os caracteres dentro dela) é uma operação estruturalmente diferente — divide por espaço, reordena os tokens, sem precisar tocar na representação interna de cada palavra. Essa variante não tem o mesmo risco de corromper caracteres multi-byte, porque as palavras permanecem intactas internamente; só a ordem delas na frase muda — útil, por exemplo, para testar como um sistema de exibição de texto lida com reordenação estrutural sem alterar o conteúdo de cada token individual.