En tant que mathématicien professionnel, je vois dans l'opérateur de similarité de Javscript ==
(également appelé "comparaison abstraite", "égalité lâche" ) une tentative de construction d'une relation d'équivalence entre entités, ce qui inclut les fonctions réflexive , symétrique et transitive . Malheureusement, deux de ces trois propriétés fondamentales échouent:
A == A
peut être faux, par exemple
NaN == NaN // false
A == B
et B == C
ensemble n'impliquent pas A == C
, par exemple
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
Seule la propriété symétrique survit:
A == B
implique B == A
, quelle violation est probablement impensable dans tous les cas et conduirait à une rébellion sérieuse;)
Pourquoi les relations d'équivalence sont-elles importantes?
Parce que c’est le type de relation le plus important et le plus répandu, étayé par de nombreux exemples et applications. L'application la plus importante est la décomposition d'entités en classes d'équivalence , ce qui est en soi un moyen très pratique et intuitif de comprendre les relations. Et le fait de ne pas être l’équivalence entraîne l’absence de classes d’équivalence, ce qui entraîne à son tour le manque d’intuitivité et de complexité inutile qui est bien connu.
Pourquoi est-ce une si terrible idée d'écrire ==
pour une relation de non-équivalence?
Parce que cela rompt notre familiarité et notre intuition, car toute relation intéressante de similarité, d’égalité, de congruence, d’isomorphisme, d’identité, etc. est une équivalence.
Conversion de type
Au lieu de s’appuyer sur une équivalence intuitive, JavaScript introduit la conversion de type:
L'opérateur d'égalité convertit les opérandes s'ils ne sont pas du même type, puis applique une comparaison stricte.
Mais comment définit-on la conversion de type? Via un ensemble de règles compliquées à de nombreuses exceptions?
Tentative de construction d'une relation d'équivalence
Booléens Clairement true
et false
ne sont pas identiques et devraient être dans des classes différentes.
Nombres. Heureusement, l'égalité des nombres est déjà bien définie, dans laquelle deux nombres différents ne sont jamais dans la même classe d'équivalence. En mathématiques, c'est. En JavaScript, la notion de nombre est quelque peu déformée via la présence du plus exotique -0
, Infinity
et -Infinity
. Notre intuition mathématique dicte que 0
et -0
devrait être dans la même classe (en fait l' -0 === 0
est true
), alors que chaque infini est une classe séparée.
Nombres et Booléens. Étant donné les classes de nombres, où plaçons-nous les booléens? false
devient semblable à 0
, alors que true
devient similaire 1
mais pas un autre nombre:
true == 1 // true
true == 2 // false
Y at-il une logique ici pour mettre en true
place 1
? Certes, 1
est distingué, mais tel est le cas -1
. Je ne vois personnellement aucune raison de convertir true
à 1
.
Et ça devient encore pire:
true + 2 // 3
true - 1 // 0
Ainsi true
est en effet converti dans 1
tous les nombres! Est-ce logique? Est-ce intuitif? La réponse est laissée comme exercice;)
Mais qu'en est-il de ceci:
1 && true // true
2 && true // true
Le seul booléen x
à l' x && true
être true
est x = true
. Ce qui prouve que les deux 1
et 2
(et tout autre nombre que 0
) se convertissent en true
! Cela montre que notre conversion échoue avec une autre propriété importante - la bijection . Cela signifie que deux entités différentes peuvent se convertir en une seule. Ce qui, en soi, ne doit pas être un gros problème. Le gros problème se pose lorsque nous utilisons cette conversion pour décrire une relation de "similitude" ou "d'égalité lâche" de ce que nous voulons l'appeler. Mais une chose est claire: il ne s'agira pas d'une relation d'équivalence ni d'une description intuitive via des classes d'équivalence.
Mais pouvons-nous faire mieux?
Au moins mathématiquement - certainement oui! Une simple relation d'équivalence entre les booléens et les nombres pourrait être construite avec false
et appartenant 0
à la même classe. Ainsi false == 0
serait la seule égalité lâche non-triviale.
Qu'en est-il des chaînes?
Nous pouvons couper les chaînes des espaces au début et à la fin pour les convertir en nombres, nous pouvons également ignorer les zéros au début:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Nous obtenons donc une règle simple pour une chaîne - découpez les espaces et les zéros devant. Soit nous obtenons un nombre ou une chaîne vide, auquel cas nous convertissons ce nombre ou ce chiffre à zéro. Ou nous n'obtenons pas de nombre, auquel cas nous ne convertissons pas et n'obtenons donc aucune nouvelle relation.
De cette façon, nous pourrions obtenir une relation d’équivalence parfaite sur l’ensemble des booléens, des nombres et des chaînes! Sauf que ... Les designers JavaScript ont évidemment un autre avis:
' ' == '' // false
Ainsi, les deux chaînes vers lesquelles les deux se convertissent 0
sont soudainement non similaires! Pourquoi ou pourquoi Selon la règle, les chaînes sont vaguement égales précisément lorsqu'elles sont strictement égales! Non seulement cette règle casse la transitivité comme on le voit, mais elle est également redondante! Quel est l'intérêt de créer un autre opérateur ==
pour le rendre strictement identique à l'autre ===
?
Conclusion
L’opérateur d’égalité lâche ==
aurait pu être très utile s’il respectait certaines lois mathématiques fondamentales. Mais comme ce n'est malheureusement pas le cas, son utilité en souffre.