Deux signes égal au lieu de trois, un caractère de moins, et un comportement radicalement différent. C'est l'opérateur qui a donné à JavaScript sa réputation de langage imprévisible, et cette réputation n'est pas volée.
Définition
L'égalité faible compare deux valeurs après les avoir converties vers un type commun. Quand les deux opérandes sont du même type, elle se comporte exactement comme l'Égalité stricte (===). Toute la difficulté vient des cas où les types diffèrent.
console.log("2" == 2); // true : la chaîne devient un nombre
console.log(2 === 2); // true, sans conversion
// L'opposé s'écrit avec !=
console.log("2" != 2); // falseCette conversion automatique porte un nom, la Coercition (conversion de type), et elle suit des règles précises que presque personne ne retient de tête. C'est bien le problème : un opérateur dont il faut mémoriser une table pour prévoir la réponse.
Ce que la conversion produit vraiment
| Comparaison | Résultat | Pourquoi |
|---|---|---|
"" == 0 | true | La chaîne vide devient zéro |
"0" == 0 | true | La chaîne devient le nombre zéro |
"" == "0" | false | Deux chaînes, aucune conversion |
[] == false | true | Les deux finissent à zéro |
null == 0 | false | null n'est comparé qu'à undefined |
Les trois premières lignes suffisent à démontrer le problème : l'opérateur n'est pas transitif. La chaîne vide est égale à zéro, la chaîne "0" est égale à zéro, et pourtant les deux chaînes ne sont pas égales entre elles. Aucune intuition ne survit à ça.
La quatrième ligne mérite d'être vue en entier : un tableau vide est vrai dans un if, et pourtant il est égal à false avec deux signes égal. Les deux mécanismes n'ont rien à voir, le premier convertit en booléen, le second en nombre.
Le seul usage qui reste recommandé
Une exception fait consensus, y compris chez ceux qui interdisent cet opérateur partout ailleurs.
const valeur = null;
// Teste null ET undefined en une seule fois
if (valeur == null) {
console.log("rien à traiter"); // s'affiche
}
// L'équivalent strict, plus long
if (valeur === null || valeur === undefined) { }La comparaison à null attrape aussi undefined, et rien d'autre : ni zéro, ni la chaîne vide, ni false. C'est le seul endroit où deux signes égal sont plus sûrs que trois, parce qu'ils évitent d'oublier l'une des deux valeurs vides.
Questions fréquentes
Pourquoi [] == ![] renvoie-t-il true ?
Parce que deux conversions s'enchaînent. La négation transforme d'abord le tableau de droite en false, puisqu'un objet est toujours vrai. Restent un tableau et un booléen, tous deux convertis en nombre : zéro d'un côté, zéro de l'autre. La comparaison est donc vraie.
Faut-il interdire cet opérateur dans un projet ?
C'est la position par défaut des outils d'analyse de code, avec une exception paramétrable pour la comparaison à null. Ce réglage est un bon compromis : il supprime les conversions accidentelles tout en gardant l'écriture courte qui rend vraiment service.
Comment comparer une saisie de formulaire à un nombre ?
En convertissant explicitement plutôt qu'en laissant l'opérateur le faire. Un champ de formulaire renvoie toujours du texte : appliquez Number (nombre)(saisie) ou parseInt, vérifiez le résultat, puis comparez avec l'Égalité stricte (===). Le code devient plus long et beaucoup plus prévisible.