Est-ce vraiment une mauvaise idée d'utiliser des accents dans du code JavaScript ?
Tags: javascript, unicode, ascii
Published: 2022-03-16 08:41:03

En JavaScript, il est possible d'ajouter des variables avec des accents ou des caractères non ASCII dans leur nom. Pour les entreprises françaises qui ont choisi d'écrire le code en français, cela permettrait de supprimer toute ambiguïté pour certains noms de variable.

Mais est-ce vraiment une bonne idée ?

---

## Un petit tour de magie

Pour commencer, voici 2 lignes de code valide en JavaScript :

```javascript
const café = 2;
console.log(café);
// Uncaught ReferenceError: café is not defined
```

Mais que s'est-il passé ? 😱 Pourquoi la valeur de la variable "café" n'est pas égale à 2 ?

C'est un peu comme un tour de magie. On n'y comprend rien, mais on sait qu'il y a un "truc" qui l'explique.

Voyons voir les principes qui se cachent derrière ce tour de passe passe.

## L'art d'encoder en Unicode

Pour afficher un caractère unicode via son code, JavaScript a défini une manière de les écrire avec des caractères ASCII. Cela commence par le caractère d'échappement `\u` suivi de :

1. soit, exactement 4 chiffres hexadécimal en majuscule ou minuscule pour les lettres de A à F : `\uXXXX` (ex: `\u039B` ou `\u039b` pour Λ)
1. soit, par 1 à 6 chiffres hexadécimal entourés d'accolade : `\u{X}`

Exemple:
- `\u{39b}` pour Λ
- `\u{10154}` pour le caractère "Mille statères acrophonique grec attique"

Ces caractères échappés peuvent être utilisés dans :
- les chaînes de caractères
- les commentaires
- les expressions régulières
- les identifiants de variable

```javascript
const \u{39b} = "LAMBDA letter, Λ, \u039b, \u{39b}";
console.log(\u{39b}); // LAMBDA letter, Λ, Λ, Λ
console.log(Λ); // LAMBDA letter, Λ, Λ, Λ
console.log(/\u{39b}/u.test(\u{39b})); // true
```

## Des caractères combinés

Certains caractères Unicode sont restitués en se combinant au caractère précédent.
Ainsi, `u\u{310}` représentera u̐.

Il est donc possible de représenter visuellement le même caractère, mais sous 2 représentations différentes.

Par exemple : é peut être vu comme le caractère `\u{e9}`, ou comme la combinaison `e\u{301}`.

## Comment peut-on nommer une variable JavaScript ?

Je ne parlerais pas ici de comment on **DOIT** nommer une variable JavaScript dans son code. Ceci est l'objet de convention de code propre à chaque projet. Mais plutôt, comment **PEUT**-on les nommer ? 

C'est-à-dire, quel est l'ensemble des possibilités que nous offre le langage pour nommer nos variables.

Une variable ne peut prendre le nom d'un mot clé réservé par le langage. Vous pouvez retrouver cette liste sur le site [ecma-international](https://262.ecma-international.org/6.0/#sec-reserved-words).

En ES2015, le nom d'une variable se décompose en 2 parties :
- le premier caractère la constituant,
- le reste de ses caractères, qui peut être vide.

Ce premier caractère peut être `$`, `_` ou n'importe quel caractère Unicode avec la propriété "ID_Start". L'ensemble de ces caractères est disponible [ici](https://codepoints.net/search?IDS=1).

Le reste des caractères peut être `$`, `_`, `\u{200c}`, `\u{200d}` ou n'importe quel caractère Unicode avec la propriété "ID_Continue". L'ensemble de ces caractères est disponible [ici](https://codepoints.net/search?IDC=1).

Si vous voulez vérifier si une chaîne de caractères est un nom de variable valide, vous pouvez l'essayer sur ce [validateur en ligne](https://mothereff.in/js-variables).

Quelques exemples de nom de variable valide :

```javascript
const π = 3.14;
const café = 2;
```

Par contre, le code suivant lèvera une erreur :

```javascript
const 😀 = "be happy";
// Uncaught SyntaxError: Invalid or unexpected token
```

## Le tour de magie dévoilé

A ce stade, peut-être avez-vous compris le mystère autour du tour de magie exposé au début :


```javascript
const café = 2;
console.log(café); // Uncaught ReferenceError: café is not defined
```

Si l'on réécrit ce code en utilisant les notations avec échappement, cela nous donne :

```javascript
const caf\u{e9} = 2;
console.log(cafe\u{301}); // Uncaught ReferenceError: café is not defined
```

On s'aperçoit alors que ce que l'on croyait être la même variable `café`, était en faite 2 variables différentes :

- une que l'on déclare et dont on affecte la valeur 2 (`caf\u{e9}`, ou café),
- une non déclarée dont on essaye de lire la valeur (`cafe\u{301}`, ou café).


Comme un bon illusionniste, notre éditeur nous a fait voir 2 choses différentes de la même manière.

Dans un autre genre, on peut également trouver des caractères qui ressemblent fortement à des caractères de ponctuation, comme :

- `\u{241}\u{321}` ou `\u{294}\u{321}` pour ?
- et `\u{1c3}` pour !.

Ce qui permettrait d'écrire ce genre de chose :

```javascript
const ǃ = 1;
const ʔ̣ = ʔ̣ => ʔ̣??!ǃ;
console.log(ʔ̣()); // false
```

## Conclusion

Nous avons vu comment écrire des caractères Unicode en JavaScript, et comment les utiliser dans des noms de variable.

Bien que l'idée d'exprimer des formules mathématiques avec des caractères grecs puisse être séduisante, et augmenter localement la lisibilité de votre code, cette pratique peut entraîner des dérives importantes sur la lisibilité, voire des bugs quasi indétectables.

Sans oublier le fait que votre serveur pourrait envoyer vos fichiers .js sous un mauvais encodage, ce qui casserait l'exécution de votre programme.

C'est pourquoi je déconseille vivement de nommer ses variables avec des accents, ou autres caractères non ASCII.

---

## Annexe

Pour aller plus loin :

Cet article m'a été inspiré par la lecture du chapitre §2.5 de :

"JavaScript: The Definitive Guide, Seventh Edition, by David Flanagan (O'Reilly). Copyright 2020 David Flanagan, 978–1–491–95202–3.".

Vous pourrez retrouver tous les caractères définis par Unicode sur : https://javascript.info/regexp-unicode

L'article utilisé pour comprendre ce qui est un identifiant de variable syntaxiquement valide : https://mathiasbynens.be/notes/javascript-identifiers-es6