Como matemático profissional, vejo no operador de uniformidade de Javscript == (também chamado de "comparação abstrata", "igualdade frouxa" ) uma tentativa de construir uma relação de equivalência entre entidades, que inclui ser reflexiva , simétrica e transitiva . Infelizmente, duas dessas três propriedades fundamentais falham:
A == A pode ser falso, por exemplo
NaN == NaN // false
A == Be B == Cjuntos não implicam A == C, por exemplo,
'1' == 1 // true
1 == '01' // true
'1' == '01' // false
Somente a propriedade simétrica sobrevive:
A == Bimplica B == A, que violação é provavelmente impensável em qualquer caso e levaria a uma rebelião séria;)
Por que as relações de equivalência são importantes?
Porque esse é o tipo de relação mais importante e predominante, suportado por vários exemplos e aplicativos. A aplicação mais importante é a decomposição de entidades em classes de equivalência , que por si só é uma maneira muito conveniente e intuitiva de entender as relações. E a falta de equivalência leva à falta de classes de equivalência, o que, por sua vez, leva à falta de intuitividade e complexidade desnecessária que é bem conhecida.
Por que é uma péssima idéia escrever ==para uma relação de não equivalência?
Porque rompe nossa familiaridade e intuição, pois literalmente qualquer relação interessante de similaridade, igualdade, congruência, isomorfismo, identidade etc. é uma equivalência.
Conversão de tipo
Em vez de confiar em uma equivalência intuitiva, o JavaScript introduz a conversão de tipo:
O operador de igualdade converte os operandos se não forem do mesmo tipo e aplica uma comparação estrita.
Mas como é definida a conversão de tipo? Através de um conjunto de regras complicadas, com inúmeras exceções?
Tentativa de construir relação de equivalência
Booleanos. Claramente truee falsenão são iguais e devem estar em classes diferentes.
Números. Felizmente, a igualdade de números já está bem definida, na qual dois números diferentes nunca estão na mesma classe de equivalência. Em matemática, é isso. Em JavaScript, a noção de número é um pouco deformada pela presença dos mais exóticos -0, Infinitye -Infinity. Nossa intuição matemática determina que 0e -0deve estar na mesma classe (de fato -0 === 0é true), enquanto que cada um dos infinitos é uma classe separada.
Números e booleanos. Dadas as classes numéricas, onde colocamos booleanos? falsetorna-se semelhante a 0, enquanto truetorna-se semelhante a, 1mas nenhum outro número:
true == 1 // true
true == 2 // false
Existe alguma lógica aqui para colocar truejunto com 1? É certo que 1se distingue, mas também é -1. Eu pessoalmente não vejo qualquer razão para converter truepara 1.
E fica ainda pior:
true + 2 // 3
true - 1 // 0
Então, de truefato, é convertido em 1entre todos os números! Isso é lógico? É intuitivo? A resposta é deixada como exercício;)
Mas e quanto a isso:
1 && true // true
2 && true // true
O único booleano xcom o x && trueser trueé x = true. O que prova que ambos 1e 2(e qualquer outro número que 0) sejam convertidos para true! O que mostra é que nossa conversão falha em outra propriedade importante - a bijeção . Significando que duas entidades diferentes podem ser convertidas na mesma. O que, por si só, não precisa ser um grande problema. O grande problema surge quando usamos essa conversão para descrever uma relação de "semelhança" ou "igualdade frouxa" do que queremos chamar. Mas uma coisa é clara - não será uma relação de equivalência e não será descrita intuitivamente por meio de classes de equivalência.
Mas podemos fazer melhor?
Pelo menos matematicamente - definitivamente sim! Uma simples relação de equivalência entre booleanos e números poderia ser construída com apenas falsee 0estar na mesma classe. Assim false == 0seria a única igualdade frouxa não trivial.
E as cordas?
Podemos cortar strings de espaços em branco no início e no final para converter em números, também podemos ignorar zeros na frente:
' 000 ' == 0 // true
' 0010 ' == 10 // true
Portanto, temos uma regra simples para uma string - apare os espaços em branco e os zeros na frente. Ou obtemos um número ou uma sequência vazia; nesse caso, convertemos para esse número ou zero. Ou não obtemos um número; nesse caso, não convertemos e, portanto, não obtemos nova relação.
Dessa forma, poderíamos obter uma relação de equivalência perfeita no conjunto total de booleanos, números e seqüências de caracteres! Exceto que ... Os designers de JavaScript obviamente têm outra opinião:
' ' == '' // false
Portanto, as duas seqüências para as quais os dois convertem 0são subitamente semelhantes! Porque ou porque? De acordo com a regra, as strings são fracamente iguais exatamente quando são estritamente iguais! Não apenas essa regra quebra a transitividade como vemos, mas também é redundante! Qual o sentido de criar outro operador ==para torná-lo estritamente idêntico ao outro ===?
Conclusão
O operador de igualdade frouxa ==poderia ter sido muito útil se estivesse cumprindo algumas leis matemáticas fundamentais. Mas como infelizmente não, sua utilidade sofre.