Conhecemos muitos operadores de comparação da matemática.
Em JavaScript eles são escritos assim:
Maior/menor que: a > b
, a < b
.
Maior/menor que ou igual: a >= b
, a <= b
.
Igual a: a == b
, observe que o duplo sinal de igualdade ==
significa o teste de igualdade, enquanto um único a = b
significa uma atribuição.
Não é igual: em matemática a notação é ≠
, mas em JavaScript é escrita como a != b
.
Neste artigo aprenderemos mais sobre os diferentes tipos de comparações, como o JavaScript as faz, incluindo peculiaridades importantes.
No final você encontrará uma boa receita para evitar problemas relacionados às “peculiaridades do JavaScript”.
Todos os operadores de comparação retornam um valor booleano:
true
– significa “sim”, “correto” ou “a verdade”.
false
– significa “não”, “errado” ou “não é a verdade”.
Por exemplo:
alerta( 2 > 1 ); //verdadeiro (correto) alerta(2 == 1); // falso (errado) alerta( 2 != 1 ); //verdadeiro (correto)
Um resultado de comparação pode ser atribuído a uma variável, assim como qualquer valor:
seja resultado = 5 > 4; //atribui o resultado da comparação alerta(resultado); // verdadeiro
Para ver se uma string é maior que outra, o JavaScript usa a chamada ordem “dicionário” ou “lexicográfica”.
Em outras palavras, as strings são comparadas letra por letra.
Por exemplo:
alerta('Z' > 'A'); // verdadeiro alert('Brilho' > 'Glee' ); // verdadeiro alert('Abelha' > 'Ser'); // verdadeiro
O algoritmo para comparar duas strings é simples:
Compare o primeiro caractere de ambas as strings.
Se o primeiro caractere da primeira string for maior (ou menor) que o da outra string, então a primeira string será maior (ou menor) que a segunda. Terminamos.
Caso contrário, se os primeiros caracteres de ambas as strings forem iguais, compare os segundos caracteres da mesma maneira.
Repita até o final de qualquer string.
Se ambas as strings terminarem com o mesmo comprimento, elas serão iguais. Caso contrário, a string mais longa será maior.
No primeiro exemplo acima, a comparação 'Z' > 'A'
chega a um resultado na primeira etapa.
A segunda comparação 'Glow'
e 'Glee'
precisa de mais etapas, pois as strings são comparadas caractere por caractere:
G
é igual a G
l
é o mesmo que l
.
o
é maior que e
. Pare aqui. A primeira string é maior.
Não é um dicionário real, mas uma ordem Unicode
O algoritmo de comparação fornecido acima é aproximadamente equivalente ao usado em dicionários ou listas telefônicas, mas não é exatamente o mesmo.
Por exemplo, o caso é importante. Uma letra maiúscula "A"
não é igual a uma letra minúscula "a"
. Qual deles é maior? O "a"
minúsculo. Por que? Porque o caractere minúsculo tem um índice maior na tabela de codificação interna que o JavaScript usa (Unicode). Voltaremos aos detalhes específicos e às consequências disso no capítulo Strings.
Ao comparar valores de tipos diferentes, o JavaScript converte os valores em números.
Por exemplo:
alerta('2'> 1); // verdadeiro, a string '2' se torna um número 2 alerta('01' == 1); // verdadeiro, a string '01' se torna um número 1
Para valores booleanos, true
torna-se 1
e false
torna-se 0
.
Por exemplo:
alerta(verdadeiro == 1); // verdadeiro alerta(falso == 0); // verdadeiro
Uma consequência engraçada
É possível que ao mesmo tempo:
Dois valores são iguais.
Um deles é true
como booleano e o outro é false
como booleano.
Por exemplo:
seja a = 0; alerta(Booleano(a)); // falso seja b = "0"; alerta(Booleano(b)); // verdadeiro alerta(a == b); // verdadeiro!
Do ponto de vista do JavaScript, esse resultado é bastante normal. Uma verificação de igualdade converte valores usando a conversão numérica (portanto, "0"
torna-se 0
), enquanto a conversão Boolean
explícita usa outro conjunto de regras.
Uma verificação regular de igualdade ==
tem um problema. Não é possível diferenciar 0
de false
:
alerta(0 == falso); // verdadeiro
A mesma coisa acontece com uma string vazia:
alerta('' == falso); // verdadeiro
Isso acontece porque operandos de diferentes tipos são convertidos em números pelo operador de igualdade ==
. Uma string vazia, assim como false
, torna-se zero.
O que fazer se quisermos diferenciar 0
de false
?
Um operador de igualdade estrito ===
verifica a igualdade sem conversão de tipo.
Em outras palavras, se a
são de tipos diferentes, então a === b
b
imediatamente false
sem uma tentativa de convertê-los.
Vamos tentar:
alerta(0 === falso); // falso, porque os tipos são diferentes
Há também um operador de “não igualdade estrita” !==
análogo a !=
.
O operador de igualdade estrita demora um pouco mais para ser escrito, mas deixa óbvio o que está acontecendo e deixa menos espaço para erros.
Há um comportamento não intuitivo quando null
ou undefined
são comparados com outros valores.
Para uma verificação estrita de igualdade ===
Esses valores são diferentes porque cada um deles é de um tipo diferente.
alerta(nulo === indefinido); // falso
Para uma verificação não estrita ==
Existe uma regra especial. Esses dois são um “doce casal”: eles se igualam (no sentido de ==
), mas não qualquer outro valor.
alerta(nulo == indefinido); // verdadeiro
Para matemática e outras comparações < > <= >=
null/undefined
são convertidos em números: null
se torna 0
, enquanto undefined
se torna NaN
.
Agora vamos ver algumas coisas engraçadas que acontecem quando aplicamos essas regras. E, o que é mais importante, como não cair numa armadilha com eles.
Vamos comparar null
com zero:
alerta(nulo > 0); // (1) falso alerta(nulo == 0); // (2) falso alerta(nulo >= 0); // (3) verdadeiro
Matematicamente, isso é estranho. O último resultado afirma que “ null
é maior ou igual a zero”, então em uma das comparações acima deve ser true
, mas ambos são falsos.
A razão é que uma verificação de igualdade ==
e comparações > < >= <=
funcionam de maneira diferente. As comparações convertem null
em um número, tratando-o como 0
. É por isso que (3) null >= 0
é verdadeiro e (1) null > 0
é falso.
Por outro lado, a verificação de igualdade ==
para undefined
e null
é definida de tal forma que, sem quaisquer conversões, eles se igualam e não são iguais a mais nada. É por isso que (2) null == 0
é falso.
O valor undefined
não deve ser comparado a outros valores:
alerta(indefinido > 0); // falso (1) alerta(indefinido < 0); // falso (2) alerta(indefinido == 0); // falso (3)
Por que ele não gosta tanto de zero? Sempre falso!
Obtemos esses resultados porque:
As comparações (1)
e (2)
retornam false
porque undefined
é convertido em NaN
e NaN
é um valor numérico especial que retorna false
para todas as comparações.
A verificação de igualdade (3)
retorna false
porque undefined
é igual apenas null
, undefined
e nenhum outro valor.
Por que revisamos esses exemplos? Deveríamos nos lembrar dessas peculiaridades o tempo todo? Bem, na verdade não. Na verdade, essas coisas complicadas gradualmente se tornarão familiares com o tempo, mas há uma maneira sólida de evitar problemas com elas:
Trate qualquer comparação com undefined/null
exceto a igualdade estrita ===
com cuidado excepcional.
Não use comparações >= > < <=
com uma variável que pode ser null/undefined
, a menos que você tenha certeza do que está fazendo. Se uma variável puder ter esses valores, verifique-os separadamente.
Os operadores de comparação retornam um valor booleano.
As strings são comparadas letra por letra na ordem do “dicionário”.
Quando valores de tipos diferentes são comparados, eles são convertidos em números (com a exclusão de uma verificação estrita de igualdade).
Os valores null
e undefined
são iguais ==
entre si e não são iguais a nenhum outro valor.
Tenha cuidado ao usar comparações como >
ou <
com variáveis que podem ocasionalmente ser null/undefined
. Verificar null/undefined
separadamente é uma boa ideia.
importância: 5
Qual será o resultado dessas expressões?
5 > 4 "maçã" > "abacaxi" "2" > "12" indefinido == nulo indefinido === nulo nulo == "n0n" nulo === +"n0n"
5 > 4 → verdadeiro "maçã" > "abacaxi" → falso "2" > "12" → verdadeiro indefinido == nulo → verdadeiro indefinido === nulo → falso nulo == "n0n" → falso nulo === +"n0n" → falso
Algumas das razões:
Obviamente, é verdade.
Comparação de dicionário, portanto falsa. "a"
é menor que "p"
.
Novamente, comparação de dicionário, o primeiro caractere "2"
é maior que o primeiro caractere "1"
.
Os valores null
e undefined
são iguais apenas entre si.
A igualdade estrita é estrita. Diferentes tipos de ambos os lados levam ao falso.
Semelhante a (4)
, null
é apenas igual a undefined
.
Igualdade estrita de diferentes tipos.