Intermédiaire 8 min de lecture 25 janvier 2025

Unicode en JavaScript: encodage, emojis et normalisation

Chaînes qui paraissent identiques mais comparent faux, emojis coupés en deux, regex qui ratent des correspondances… Avec JavaScript et Unicode, le diable se cache dans les détails: UTF‑16, points de code, normalisation, ZWJ et sélecteurs de variation. Voici l’essentiel pour manipuler des chaînes fiables et prévisibles dans vos applications.

Comprendre Unicode en JavaScript

JavaScript stocke ses chaînes en UTF‑16. Il faut distinguer unités de code (16 bits) et points de code Unicode pour éviter des erreurs.

Points clés à connaître pour travailler correctement avec Unicode en JavaScript :

1 Unités de code UTF‑16 en JavaScript

length compte des unités de code, pas des caractères utilisateur.

"👍".length === 2, Array.from("👍").length === 1

2 Paires de substitution (surrogate pairs)

Les points de code > U+FFFF sont encodés en deux unités de code.

"👍" = U+D83D U+DC4D (point de code U+1F44D)

3 Points de code et espaces Unicode fréquents

Certains blancs et séparateurs perturbent la comparaison et le parsing :

NBSP (U+00A0) - Non-breaking space
ZWSP (U+200B) - Zero Width Space
ZWNBSP (U+FEFF) - Zero Width No-Break Space
Thin Space (U+2009), Hair Space (U+200A)

4 Marques techniques et modificateurs

Éléments qui changent le rendu ou la sémantique des glyphes :

ZWJ (U+200D) - Zero Width Joiner
Variation Selector-16 (U+FE0F) - Emoji vs texte
BOM (U+FEFF) - Byte Order Mark en début de fichier

Problèmes classiques

Copier-coller d’emojis ou lettres accentuées

Ajoute ZWJ, sélecteurs de variation ou normalisation différente (NFC/NFD) dans les données.

Tests unitaires qui échouent

Comparaisons strictes fausses entre "é" (U+00E9) et "é" (e + U+0301), longueurs inattendues.

trim() inefficace

Ne supprime pas ZWSP/ZWJ ni certaines marques combinantes utilisées avec Unicode.

Regex \s ou \w incomplètes

Sans le flag u, \w est ASCII‑centré et . peut couper des paires de substitution.

Exemple de problème courant :

# Chaînes visuellement identiques, formes Unicode différentes
string1 = "é" # NFC (U+00E9)
string2 = "é" # NFD: "e" + U+0301
assert string1 === string2 # ❌ Échec

Symptômes qui doivent vous alerter

🚨 Signaux d'alarme

!
length retourne 2 pour un seul emoji affiché
!
slice() ou substring() coupe un drapeau ou un pictogramme
!
Une regex sans flag u a des résultats incohérents sur des accents/emoji
!
Le curseur saute ou affiche un carré sur certains caractères combinés
!
Un collage dans un REPL/terminal casse une commande à cause d’un ZWSP

Comment les détecter

Solution recommandée : Clean ASCII

Clean ASCII repère immédiatement les caractères Unicode ambigus dans vos chaînes JavaScript. Il met en évidence ZWJ, ZWSP, sélecteurs de variation, marques combinantes et caractères de contrôle.

✅ Détection automatique

NBSP, ZWSP, ZWJ, BOM, soft hyphens, marques combinantes

📊 Analyse précise

Points de code, positions exactes, nature du caractère

🧹 Nettoyage ciblé

Remplacement ou suppression des caractères problématiques

💾 Export propre

Texte nettoyé prêt pour vos scripts et tests

Autres méthodes de détection

Affichage dans l'éditeur

Activez "render whitespace", "reveal unicode" dans VS Code, JetBrains, Sublime
Installez un linter qui surligne NBSP, ZWSP, ZWJ et combinaisons suspectes

En ligne de commande (Unix)

# Trouver les octets non ASCII (UTF‑8)
grep -P "[^\x09\x0A\x0D\x20-\x7E]" fichier.txt
# Voir les fins de ligne et tabulations
sed -n l fichier.txt
# Afficher les caractères de contrôle
cat -A fichier.txt
# Inspecter les codes hexadécimaux
hexdump -C fichier.txt

En code

JavaScript

Array.from(str).map(c => c.codePointAt(0).toString(16))

Python

[f"{ord(c):04x}" for c in s if ord(c) > 0x7F or ord(c) < 0x20]

Excel / Google Sheets

UNICODE(MID(cellule;position;1))

Nettoyer et prévenir

🚀 Solution rapide avec Clean ASCII

Avant d’écrire des utilitaires, utilisez Clean ASCII pour traquer et supprimer les caractères Unicode piégeux dans vos chaînes JavaScript.

Détection automatique
Nettoyage intelligent
Export immédiat

Méthodes techniques avancées

🔧 Normaliser

Utilisez str.normalize("NFC") ou "NFKC" pour homogénéiser
Supprimez les BOM inutiles dans les fichiers UTF‑8
Uniformisez les fins de ligne (dos2unix, gitattributes)

🧹 Filtrer

Écrivez des fonctions stripZeroWidth() pour retirer ZWSP/ZWJ
Remplacez NBSP par espace simple si nécessaire
Bloquez les caractères de contrôle hors LF/CR/HT dans les inputs

⚙️ Automatiser

Hooks pre-commit refusant des fichiers avec caractères hors plage attendue
Tests sur la sanitation et la normalisation des entrées utilisateur
Linting CI (regex avec flag u, règles ESLint pertinentes)

Checklist rapide

Fichiers en UTF‑8 sans BOM
Fins de ligne uniformes via gitattributes
Éditeur affichant blancs, contrôles et caractères invisibles
Fonctions utilitaires pour points de code et grapphèmes (Intl.Segmenter)
Tests vérifiant l’absence de caractères de contrôle indésirables
Documentation équipe sur UTF‑16, flag u, normalisation

Conclusion

Unicode en JavaScript est subtil: unités de code, points de code, combinaisons et modificateurs impactent vos chaînes.

Adoptez la normalisation, utilisez le flag u en regex, segmentez par grapphèmes au besoin et détectez les caractères invisibles pour éviter les bugs chroniques.

Analysez vos chaînes JavaScript/Unicode maintenant

Utilisez notre outil pour repérer et nettoyer les caractères Unicode problématiques dans vos textes.

Analyser mon texte