Aller au contenu
Retour au blog

"Convertir les emoji en Unicode avec JavaScript"

Leibniz Li

@leibnizli
+

Les emoji ne sont pas toujours de simples caractères : beaucoup appartiennent aux plans supplémentaires Unicode. Comprendre leur traitement en JavaScript est essentiel pour les longueurs de chaîne, les bases de données et l’affichage multiplateforme.

Le problème : pourquoi .length peut tromper

Les chaînes JavaScript utilisent UTF-16. A ou ☃ appartiennent au plan multilingue de base (BMP) et occupent une unité de 16 bits. Des emoji comme 😀 sont dans les plans supplémentaires et utilisent deux unités de 16 bits, une paire de substitution.

'A'.length;    // 1 (BMP)
'☃'.length;    // 1 (BMP)
'😀'.length;    // 2 (Supplementary Plane - Surrogate Pair)
'👨‍👩‍👧‍👦'.length; // 11 (Wait, what? See "ZWJ" below)

Solution 1 : String.prototype.codePointAt()

Avant ES6, charCodeAt() ne renvoyait que la première moitié d’une paire de substitution. codePointAt() permet désormais d’obtenir le point de code Unicode complet.

const emoji = '😀';

// ❌ The old way (Incorrect for emojis)
console.log(emoji.charCodeAt(0)); // 55357 (Surrogate lead)

// ✅ The modern way
console.log(emoji.codePointAt(0)); // 128512
console.log(emoji.codePointAt(0).toString(16)); // "1f600"

Solution 2 : String.fromCodePoint()

Pour transformer un nombre Unicode en emoji visible, utilisez la méthode statique String.fromCodePoint().

// Decimal
String.fromCodePoint(128512); // "😀"

// Hexadecimal
String.fromCodePoint(0x1F600); // "😀"

// Multiple points
String.fromCodePoint(0x1F1FA, 0x1F1F8); // "🇺🇸"

Conversion de plusieurs caractères

Une chaîne contenant plusieurs emoji et caractères peut être convertie d’un coup. L’opérateur de décomposition [...] parcourt les points de code Unicode sans couper les paires de substitution.

1. De la chaîne aux nombres : encodage

Utilisez .map() pour obtenir un tableau de valeurs Unicode décimales ou hexadécimales :

const text = "Hi 😀 🚀";

// Convert to Decimal numbers
const decimals = [...text].map(char => char.codePointAt(0));
console.log(decimals); 
// [72, 105, 32, 128512, 32, 128640]

// Convert to Hexadecimal strings (common for CSS/JS escape)
const hexCodes = [...text].map(char => `0x${char.codePointAt(0).toString(16)}`);
console.log(hexCodes);
// ["0x48", "0x69", "0x20", "0x1f600", "0x20", "0x1f680"]

2. Des nombres à la chaîne : décodage

Pour retrouver une chaîne lisible, combinez String.fromCodePoint et la syntaxe de décomposition ... :

const myNumbers = [128512, 128640, 9731];

// This "spreads" the array items as individual arguments
const result = String.fromCodePoint(...myNumbers);
console.log(result); // "😀🚀☃"

3. Utiliser une boucle simple

Si .map() vous semble difficile, une boucle for...of convient aussi :

const input = "🍎🍊";
for (let char of input) {
  let hex = char.codePointAt(0).toString(16);
  console.log(`Character: ${char} -> Unicode: U+${hex.toUpperCase()}`);
}
// Character: 🍎 -> Unicode: U+1F34E
// Character: 🍊 -> Unicode: U+1F34A

Emoji complexes : liants sans chasse, ou ZWJ

Certains emoji semblent former un seul caractère, mais sont des séquences de points Unicode reliés par un liant sans chasse (ZWJ, \u200D).

La famille 👨‍👩‍👧‍👦 se compose de : homme + ZWJ + femme + ZWJ + fille + ZWJ + garçon.

Utilisez l’opérateur de décomposition [...] ou Array.from() pour parcourir correctement les points de code. Ils ne traitent toutefois pas toute la famille comme un seul caractère affiché :

const complexEmoji = '👨‍👩‍👧‍👦';

// ❌ Standard split (breaks the emoji)
console.log(complexEmoji.split('')); 
// ["\ud83d", "\udc68", "‍", "\ud83d", ...]

// ✅ Unicode-aware iteration
const points = [...complexEmoji];
console.log(points); 
// ["👨", "‍", "👩", "‍", "👧", "‍", "👦"]

// 1. Get code points as Hexadecimal (commonly used in docs)
const hexCodes = [...complexEmoji].map(c => `0x${c.codePointAt(0).toString(16)}`);
console.log(hexCodes);
// ["0x1f468", "0x200d", "0x1f469", "0x200d", "0x1f467", "0x200d", "0x1f466"]

// 2. Get code points as Decimal (Non-Hexadecimal)
const decimalCodes = [...complexEmoji].map(c => c.codePointAt(0));
console.log(decimalCodes);
// [128104, 8205, 128105, 8205, 128103, 8205, 128102]

// 3. Convert Decimal back to Emoji
console.log(String.fromCodePoint(...decimalCodes)); 
// "👨‍👩‍👧‍👦"

// 4. Convert Hex strings back to Emoji
const emojiFromHex = String.fromCodePoint(...hexCodes);
console.log(emojiFromHex); 
// "👨‍👩‍👧‍👦"

Cas pratiques

  1. Base de données : configurez MySQL, par exemple, en utf8mb4 pour stocker ces caractères sur quatre octets.
  2. Limite de saisie : [...str].length compte les points de code, tandis que str.length compte les unités UTF-16. Une séquence ZWJ comporte encore plusieurs points et ne correspond donc pas à un unique caractère perçu.
  3. Rendu personnalisé : utile pour les jeux Canvas et composants d’interface performants.

Besoin d’un outil interactif ?

Essayez notre convertisseur Unicode et emoji en ligne pour convertir en temps réel dans les deux sens entre texte, hexadécimal et séquences d’échappement CSS ou JS.

Essayer le convertisseur Unicode en ligne →