Como matemático profesional, veo en el operador de igualdad de Javscript == (también llamado "comparación abstracta", "igualdad suelta" ) un intento de construir una relación de equivalencia entre entidades, que incluye ser reflexivo , simétrico y transitivo . Desafortunadamente, dos de estas tres propiedades fundamentales fallan:
A == A puede ser falso, por ejemplo
NaN == NaN // false
A == By B == Cjuntos no implican A == C, por ejemplo
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
Solo la propiedad simétrica sobrevive:
A == Bimplica B == A, qué violación es probablemente impensable en cualquier caso y conduciría a una rebelión grave;)
¿Por qué importan las relaciones de equivalencia?
Porque ese es el tipo de relación más importante y frecuente, respaldado por numerosos ejemplos y aplicaciones. La aplicación más importante es la descomposición de entidades en clases de equivalencia , que es en sí misma una forma muy conveniente e intuitiva de entender las relaciones. Y no ser equivalencia conduce a la falta de clases de equivalencia, lo que a su vez conduce a la falta de intuición y complejidad innecesaria que es bien conocida.
¿Por qué es una idea tan terrible escribir ==para una relación de no equivalencia?
Porque rompe nuestra familiaridad e intuición, ya que literalmente cualquier relación interesante de similitud, igualdad, congruencia, isomorfismo, identidad, etc. es una equivalencia.
Conversión de tipo
En lugar de confiar en una equivalencia intuitiva, JavaScript introduce la conversión de tipos:
El operador de igualdad convierte los operandos si no son del mismo tipo, luego aplica una comparación estricta.
Pero, ¿cómo se define la conversión de tipo? ¿A través de un conjunto de reglas complicadas con numerosas excepciones?
Intento de construir una relación de equivalencia
Booleanos. Claramente truey falseno son lo mismo y deben estar en diferentes clases.
Números. Afortunadamente, la igualdad de números ya está bien definida, en la que dos números diferentes nunca están en la misma clase de equivalencia. En matemáticas, eso es. En JavaScript, la noción de número está algo deformada por la presencia de los más exóticos -0, Infinityy -Infinity. Nuestra intuición matemática dicta que 0y -0debe estar en la misma clase (de hecho lo -0 === 0es true), mientras que cada uno de los infinitos es una clase separada.
Números y booleanos. Dadas las clases de números, ¿dónde ponemos los booleanos? falsese vuelve similar a 0, mientras que se truevuelve similar a, 1pero no a otro número:
true == 1 // true
true == 2 // false
¿Hay alguna lógica aquí para truearmar 1? Es cierto que 1se distingue, pero también lo es -1. Yo personalmente no veo ninguna razón para convertir truea 1.
Y se pone aún peor:
true + 2 // 3
true - 1 // 0
Por truelo tanto, de hecho se convierte 1entre todos los números! ¿Es lógico? ¿Es intuitivo? La respuesta se deja como ejercicio;)
Pero qué hay de esto:
1 && true // true
2 && true // true
El único booleano xcon x && trueser truees x = true. Lo que demuestra que tanto 1y 2(y cualquier otro número que 0) se convierten a true! Lo que muestra es que nuestra conversión falla otra propiedad importante: ser biyección . Lo que significa que dos entidades diferentes pueden convertir a la misma. Lo cual, por sí mismo, no tiene que ser un gran problema. El gran problema surge cuando usamos esta conversión para describir una relación de "similitud" o "igualdad suelta" de lo que queramos llamarlo. Pero una cosa está clara: no será una relación de equivalencia y no se describirá intuitivamente a través de clases de equivalencia.
¿Pero podemos hacerlo mejor?
Al menos matemáticamente, ¡definitivamente sí! Se podría construir una relación de equivalencia simple entre booleanos y números con solo falsey 0estar en la misma clase. Entonces false == 0sería la única igualdad suelta no trivial.
¿Qué pasa con las cuerdas?
Podemos recortar cadenas de espacios en blanco al principio y al final para convertirlas en números, también podemos ignorar ceros al frente:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Entonces obtenemos una regla simple para una cadena: recortar los espacios en blanco y los ceros al frente. O obtenemos un número o una cadena vacía, en cuyo caso la convertimos a ese número o cero. O no obtenemos un número, en cuyo caso no convertimos y, por lo tanto, no obtenemos una nueva relación.
¡De esta forma podríamos obtener una relación de equivalencia perfecta en el conjunto total de booleanos, números y cadenas! Excepto que ... los diseñadores de JavaScript obviamente tienen otra opinión:
' ' == '' // false
¡Entonces las dos cadenas a las que ambos se convierten de 0repente no son similares! ¿Por qué o por qué? De acuerdo con la regla, las cadenas son más o menos iguales precisamente cuando son estrictamente iguales. ¡No solo esta regla rompe la transitividad como vemos, sino que también es redundante! ¿Cuál es el punto de crear otro operador ==para que sea estrictamente idéntico al otro ===?
Conclusión
El operador de igualdad flexible ==podría haber sido muy útil si respetara algunas leyes matemáticas fundamentales. Pero como lamentablemente no, su utilidad sufre.