Conhecemos muitos operadores de comparação de matemática.
Em JavaScript eles são escritos assim:
- Mais/mais que:
a > b
,a < b
. - Mais/mais que ou igual a::
a >= b
,a <= b
. - Equaisais:
a == b
, por favor note o sinal de dupla igualdade==
significa o teste de igualdade, enquanto um simplesa = b
significa uma atribuição. - Não é igual. Em matemática a notação é
≠
, mas em JavaScript está escrito comoa != b
.
Neste artigo vamos aprender mais sobre diferentes tipos de comparações, como o JavaScript as faz, incluindo importantes peculiaridades.
No final você vai encontrar uma boa receita para evitar problemas relacionados ao “JavaScript quirks”.
Booleano é o resultado
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:
alert( 2 > 1 ); // true (correct)alert( 2 == 1 ); // false (wrong)alert( 2 != 1 ); // true (correct)
Um resultado de comparação pode ser atribuído a uma variável, como qualquer valor:
let result = 5 > 4; // assign the result of the comparisonalert( result ); // true
Comparação de cordas
Para ver se uma corda é maior que outra, o JavaScript usa a chamada ordem “dicionário” ou “lexicográfico”.
Em outras palavras, as strings são comparadas letra por letra.
Por exemplo:
alert( 'Z' > 'A' ); // truealert( 'Glow' > 'Glee' ); // truealert( 'Bee' > 'Be' ); // true
O algoritmo para comparar duas strings é simples:
- Comparar 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 é maior (ou menor) que a segunda. Estamos prontos.
- Outros, se os primeiros caracteres de ambas as strings forem os mesmos, compare os segundos caracteres da mesma maneira.
- Reprima até o final de qualquer uma das strings.
- Se ambas as strings terminarem no mesmo comprimento, então elas são iguais. Caso contrário, a string mais longa é maior.
No primeiro exemplo acima, a comparação 'Z' > 'A'
chega a um resultado no primeiro passo.
A segunda comparação 'Glow'
e 'Glee'
precisa de mais passos, pois as cordas são comparadas caracter por caracter:
-
G
é o mesmo queG
. -
l
é o mesmo quel
. -
o
é maior quee
. Pare aqui. A primeira string é maior.
O algoritmo de comparação dado acima é aproximadamente equivalente ao usado em dicionários ou listas telefônicas, mas não é exatamente o mesmo.
Por exemplo, o caso importa. Uma letra maiúscula "A"
não é igual à minúscula "a"
. Qual delas é maior? A letra minúscula "a"
. Qual é a maior? Porque o caractere minúsculo tem um índice maior na tabela de codificação interna que o JavaScript usa (Unicode). Voltaremos aos detalhes e consequências específicas no capítulo Strings.
Comparação de diferentes tipos
Ao comparar valores de diferentes tipos, o JavaScript converte os valores para números.
Por exemplo:
alert( '2' > 1 ); // true, string '2' becomes a number 2alert( '01' == 1 ); // true, string '01' becomes a number 1
Para valores booleanos, true
torna-se 1
e false
torna-se 0
.
Por exemplo:
alert( true == 1 ); // truealert( false == 0 ); // true
É possível que ao mesmo tempo:
- Dois valores sejam iguais.
- Um deles é
true
como um booleano e o outro éfalse
como um booleano.
Por exemplo:
let a = 0;alert( Boolean(a) ); // falselet b = "0";alert( Boolean(b) ); // truealert(a == b); // true!
Do ponto de vista do JavaScript, este resultado é bastante normal. Uma verificação de igualdade converte valores usando a conversão numérica (daí "0"
torna-se 0
), enquanto que a explícita Boolean
conversão usa outro conjunto de regras.
Igualdade restrita
Uma verificação de igualdade regular ==
tem um problema. Não consegue diferenciar 0
de false
:
alert( 0 == false ); // true
A mesma coisa acontece com uma cadeia vazia:
alert( '' == false ); // true
Isto acontece porque operandos de diferentes tipos são convertidos em números pelo operador de igualdade ==
. Uma string vazia, assim como false
, torna-se um zero.
O que fazer se quisermos diferenciar 0
de false
?
Um operador de igualdade rigoroso ===
verifica a igualdade sem conversão de tipo.
Em outras palavras, se a
e b
são de tipos diferentes, então a === b
retorna imediatamente false
sem uma tentativa de convertê-los.
Vamos tentar:
alert( 0 === false ); // false, because the types are different
Existe também um operador de “estrita não-qualidade” !==
análogo a !=
.
O operador de igualdade estrita é um pouco mais longo de escrever, mas torna óbvio o que se passa e deixa menos espaço para erros.
Comparação com nulo e indefinido
Existe um comportamento não-intuitivo quando null
ou undefined
são comparados com outros valores.
Para uma verificação de igualdade rigorosa===
Estes valores são diferentes, porque cada um deles é de um tipo diferente.
alert( null === undefined ); // false
Para uma verificação não restritiva==
Existe uma regra especial. Estes dois são um “casal doce”: eles se igualam (no sentido de ==
), mas não qualquer outro valor.
alert( null == undefined ); // true
Para matemática e outras comparações< > <= >=
null/undefined
são convertidos em números: null
torna-se 0
, enquanto undefined
torna-se NaN
.
Agora vamos ver algumas coisas engraçadas que acontecem quando aplicamos estas regras. E, o que é mais importante, como não cair numa armadilha com elas.
Resultado estranho: nulo vs 0
Vamos comparar null
com um zero:
alert( null > 0 ); // (1) falsealert( null == 0 ); // (2) falsealert( null >= 0 ); // (3) true
Matematicamente, isso é estranho. O último resultado diz que “null
é maior ou igual a zero”, então em uma das comparações acima deve ser true
, mas ambas são falsas.
A razão é que uma verificação de igualdade ==
e comparações > < >= <=
funcionam de forma diferente. As comparações convertem null
para 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 qualquer conversão, eles se igualam e não se igualam a mais nada. É por isso que (2) null == 0
é falso.
Um incomparável indefinido
O valor undefined
não deve ser comparado com outros valores:
alert( undefined > 0 ); // false (1)alert( undefined < 0 ); // false (2)alert( undefined == 0 ); // false (3)
Por que é que não gosta tanto de zero? Sempre falso!
Obtemos estes resultados porque:
- Comparações
(1)
e(2)
retornofalse
porqueundefined
é convertido paraNaN
eNaN
é um valor numérico especial que retornafalse
para todas as comparações. - A verificação de igualdade
(3)
retornafalse
porqueundefined
só é igual anull
,undefined
, e nenhum outro valor.
Problemas ovóides
Por que revimos estes exemplos? Devemos nos lembrar dessas peculiaridades o tempo todo? Bem, nem por isso. Na verdade, estas coisas complicadas vão-se tornando gradualmente familiares com o tempo, mas há uma forma sólida de evitar problemas com elas:
- Trate qualquer comparação com
undefined/null
excepto a estrita igualdade===
com cuidados excepcionais. - Não use comparações
>= > < <=
com uma variável que pode sernull/undefined
, a menos que esteja realmente seguro do que está a fazer. Se uma variável pode ter esses valores, verifique por eles separadamente.
Resumo
- Os operadores de comparação retornam um valor booleano.
- Astringas 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 de igualdade rigorosa).
- Os valores
null
eundefined
iguais==
um ao outro e não são iguais a nenhum outro valor. - Tenha cuidado ao usar comparações como
>
ou<
com variáveis que podem ocasionalmente sernull/undefined
. Verificar pornull/undefined
separadamente é uma boa ideia.