Qual operador igual (== vs ===) deve ser usado em comparações de JavaScript?
Estou usando JSLint para passar por JavaScript e ele está retornando muitas sugestões para substituir ==
(dois sinais de igual) por ===
(três sinais de igual) ao fazer coisas como comparar idSele_UNVEHtype.value.length == 0
dentro de uma if
instrução.
Existe um benefício de desempenho para substituir ==
por ===
?
Qualquer melhoria de desempenho seria bem-vinda, pois existem muitos operadores de comparação.
Se nenhuma conversão de tipo ocorrer, haverá um ganho de desempenho ==
?
Respostas
O operador de igualdade estrita ( ===
) se comporta de forma idêntica ao operador de igualdade abstrato ( ==
), exceto que nenhuma conversão de tipo é feita e os tipos devem ser iguais para serem considerados iguais.
Referência: Tutorial Javascript: Operadores de comparação
O ==
operador irá comparar a igualdade após fazer qualquer conversão de tipo necessária . O ===
operador não fará a conversão, portanto, se dois valores não forem do mesmo tipo ===
, simplesmente retornará false
. Ambos são igualmente rápidos.
Para citar o excelente JavaScript de Douglas Crockford : The Good Parts ,
JavaScript tem dois conjuntos de operadores de igualdade:
===
e!==
, e seus gêmeos malvados==
e!=
. Os bons funcionam da maneira que você esperaria. Se os dois operandos forem do mesmo tipo e tiverem o mesmo valor, então===
produztrue
e!==
produzfalse
. Os gêmeos maus fazem a coisa certa quando os operandos são do mesmo tipo, mas se forem de tipos diferentes, eles tentam coagir os valores. as regras pelas quais eles fazem isso são complicadas e inesquecíveis. Estes são alguns dos casos interessantes:'' == '0' // false 0 == '' // true 0 == '0' // true false == 'false' // false false == '0' // true false == undefined // false false == null // false null == undefined // true ' \t\r\n ' == 0 // true
A falta de transitividade é alarmante. Meu conselho é nunca usar os gêmeos do mal. Em vez disso, sempre use
===
e!==
. Todas as comparações mostradas produzemfalse
com o===
operador.
Atualizar:
Um bom ponto foi levantado por @Casebash nos comentários e na resposta de @Phillipe Laybaert sobre objetos. Para objetos, e agir de forma consistente com o outro (exceto em um caso especial).==
===
var a = [1,2,3];
var b = [1,2,3];
var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };
var e = "text";
var f = "te" + "xt";
a == b // false
a === b // false
c == d // false
c === d // false
e == f // true
e === f // true
O caso especial é quando você compara uma primitiva com um objeto que avalia a mesma primitiva, devido ao seu método toString
ou valueOf
. Por exemplo, considere a comparação de uma primitiva de string com um objeto de string criado usando o String
construtor.
"abc" == new String("abc") // true
"abc" === new String("abc") // false
Aqui, o ==
operador está verificando os valores dos dois objetos e retornando true
, mas ===
está vendo que eles não são do mesmo tipo e retornando false
. Qual está correto? Isso realmente depende do que você está tentando comparar. Meu conselho é ignorar totalmente a questão e simplesmente não usar o String
construtor para criar objetos de string a partir de literais de string.
Referência
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
Usando o ==
operador ( igualdade )
true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2; //true, because "2" is converted to 2 and then compared
Usando o ===
operador ( identidade )
true === 1; //false
"2" === 2; //false
Isso ocorre porque o operador de igualdade ==
faz coerção de tipo , o que significa que o interpretador tenta implicitamente converter os valores antes de comparar.
Por outro lado, o operador de identidade ===
não faz coerção de tipo e, portanto, não converte os valores ao comparar e é, portanto, mais rápido (de acordo com Este teste de benchmark JS ), pois pula uma etapa.
Uma representação pictórica interessante da comparação de igualdade entre ==
e ===
.
Fonte: http://dorey.github.io/JavaScript-Equality-Table/
var1 === var2
Ao usar
===
para teste de igualdade de JavaScript, tudo é como está. Nada é convertido antes de ser avaliado.
var1 == var2
Ao usar
==
para testes de igualdade de JavaScript, ocorrem algumas conversões estranhas.
Moral da história:
Use a
===
menos que você entenda completamente as conversões que ocorrem com==
.
Nas respostas aqui, não li nada sobre o que significa igual . Alguns dirão que ===
significa igual e do mesmo tipo , mas isso não é verdade. Na verdade, significa que ambos os operandos fazem referência ao mesmo objeto ou, no caso de tipos de valor, têm o mesmo valor .
Então, vamos pegar o seguinte código:
var a = [1,2,3];
var b = [1,2,3];
var c = a;
var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true
O mesmo aqui:
var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;
var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true
Ou ainda:
var a = { };
var b = { };
var c = a;
var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true
Esse comportamento nem sempre é óbvio. A história é mais do que ser igual e ser do mesmo tipo.
A regra é:
Para tipos de valor (números):
a === b
retorna verdadeiro sea
eb
tiver o mesmo valor e for do mesmo tipo
Para tipos de referência:
a === b
retorna verdadeiro sea
e fazb
referência exatamente ao mesmo objeto
Para strings:
a === b
retorna verdadeiro sea
eb
forem strings e contiverem exatamente os mesmos caracteres
Strings: o caso especial ...
Strings não são tipos de valor, mas em Javascript se comportam como tipos de valor, então serão "iguais" quando os caracteres na string forem iguais e quando tiverem o mesmo comprimento (conforme explicado na terceira regra)
Agora fica interessante:
var a = "12" + "3";
var b = "123";
alert(a === b); // returns true, because strings behave like value types
Mas e quanto a isso ?:
var a = new String("123");
var b = "123";
alert(a === b); // returns false !! (but they are equal and of the same type)
Eu pensei que as strings se comportam como tipos de valor. Bem, depende de quem você pergunta ... Nesse caso, aeb não são do mesmo tipo. a
é do tipo Object
, enquanto b
é do tipo string
. Lembre-se de que criar um objeto string usando o String
construtor cria algo do tipo Object
que se comporta como string na maioria das vezes .
Deixe-me adicionar este conselho:
Em caso de dúvida, leia a especificação !
ECMA-262 é a especificação de uma linguagem de script da qual o JavaScript é um dialeto. É claro que, na prática, importa mais como os navegadores mais importantes se comportam do que uma definição esotérica de como algo deve ser tratado. Mas é útil entender porque new String ("a")! == "a" .
Deixe-me explicar como ler a especificação para esclarecer essa questão. Vejo que neste tópico muito antigo ninguém teve uma resposta para o efeito tão estranho. Portanto, se você puder ler uma especificação, isso o ajudará tremendamente em sua profissão. É uma habilidade adquirida. Então, vamos continuar.
Pesquisar no arquivo PDF por === me leva à página 56 da especificação: 11.9.4. O operador Strict Equals (===) , e depois de percorrer as especificidades, encontro:
11.9.6 O algoritmo de comparação de igualdade estrita
A comparação x === y, onde x e y são valores, produz verdadeiro ou falso . Essa comparação é realizada da seguinte maneira:
1. Se Type (x) for diferente de Type (y), retorne false .
2. Se Type (x) for Undefined, retorne true .
3. Se Type (x) for Null, retorne true .
4. Se Tipo (x) não for Número, vá para a etapa 11.
5. Se x for NaN , retorne falso .
6. Se y for NaN , retorna falso .
7. Se x for o mesmo valor numérico de y, retorne verdadeiro .
8. Se x for +0 ey for −0, retorne verdadeiro .
9. Se x for −0 ey for +0, retorne verdadeiro .
10. Retorne falso .
11. Se Type (x) for String, então retorne true se xey forem exatamente a mesma sequência de caracteres (mesmo comprimento e mesmos caracteres nas posições correspondentes); caso contrário, retorna falso .
12. Se Type (x) for Boolean, retorne true se xey forem ambos verdadeiros ou ambos falsos ; caso contrário, retorna falso .
13. Retorne verdadeiro se x e y se referem ao mesmo objeto ou se eles se referem a objetos unidos entre si (ver 13.1.2). Caso contrário, retorna falso .
Interessante é a etapa 11. Sim, as strings são tratadas como tipos de valor. Mas isso não explica por que new String ("a")! == "a" . Temos um navegador que não está em conformidade com ECMA-262?
Não tão rápido!
Vamos verificar os tipos de operandos. Experimente você mesmo envolvendo-os em typeof () . Descobri que new String ("a") é um objeto e a etapa 1 é usada: retornar false se os tipos forem diferentes.
Se você está se perguntando por que new String ("a") não retorna uma string, que tal algum exercício de leitura de uma especificação? Divirta-se!
Aidiakapi escreveu isso em um comentário abaixo:
Da especificação
11.2.2 O novo operador :
Se Type (construtor) não for Object, lance uma exceção TypeError.
Em outras palavras, se String não fosse do tipo Object, ela não poderia ser usada com o novo operador.
new sempre retorna um Object, mesmo para construtores de String também. E ai! A semântica de valor para strings (consulte a etapa 11) foi perdida.
E isso finalmente significa: new String ("a")! == "a" .
Testei isso no Firefox com Firebug usando um código como este:
console.time("testEquality");
var n = 0;
while (true) {
n++;
if (n == 100000)
break;
}
console.timeEnd("testEquality");
e
console.time("testTypeEquality");
var n = 0;
while (true) {
n++;
if (n === 100000)
break;
}
console.timeEnd("testTypeEquality");
Meus resultados (testados cinco vezes cada e com média):
==: 115.2
===: 114.4
Então, eu diria que a diferença minúscula (isso é mais de 100.000 iterações, lembre-se) é insignificante. O desempenho não é uma razão para fazer ===
. Digite segurança (bem, tão seguro quanto você conseguirá em JavaScript), e a qualidade do código é.
Em PHP e JavaScript, é um operador de igualdade estrita. O que significa que ele irá comparar o tipo e os valores.
Em JavaScript, significa o mesmo valor e tipo.
Por exemplo,
4 == "4" // will return true
mas
4 === "4" // will return false
O === operador é chamado um operador de comparação rigorosa, que não diferem do == operador.
Vamos pegar 2 vars a e b.
Para que "a == b" seja avaliado como verdadeiro, a e b precisam ter o mesmo valor .
No caso de "a === b" a e b devem ter o mesmo valor e também o mesmo tipo para que seja avaliado como verdadeiro.
Veja o seguinte exemplo
var a = 1;
var b = "1";
if (a == b) //evaluates to true as a and b are both 1
{
alert("a == b");
}
if (a === b) //evaluates to false as a is not the same type as b
{
alert("a === b");
}
Em resumo ; usar o operador == pode ser avaliado como verdadeiro em situações em que você não deseja que isso aconteça, então usar o operador === seria mais seguro.
No cenário de uso de 90%, não importa qual você usa, mas é útil saber a diferença quando você obtém algum comportamento inesperado um dia.
Por que ==
é tão imprevisível?
O que você ganha quando compara uma string vazia ""
com o número zero 0
?
true
Sim, está certo de acordo com ==
uma string vazia e o número zero são ao mesmo tempo.
E não termina aí, aqui está outro:
'0' == false // true
As coisas ficam muito estranhas com matrizes.
[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true
Então mais estranho com cordas
[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!
Fica pior:
Quando é igual não é igual?
let A = '' // empty string
let B = 0 // zero
let C = '0' // zero string
A == B // true - ok...
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!
Deixe-me dizer de novo:
(A == B) && (B == C) // true
(A == C) // **FALSE**
E isso é apenas a coisa maluca que você consegue com primitivos.
É um novo nível de loucura quando você usa ==
com objetos.
Neste ponto, você provavelmente está se perguntando ...
Por que isso acontece?
Bem, é porque ao contrário de "triplo igual" ( ===
) que apenas verifica se dois valores são iguais.
==
faz um monte de outras coisas .
Ele tem tratamento especial para funções, tratamento especial para nulos, indefinidos, strings, etc.
É muito estranho.
Na verdade, se você tentasse escrever uma função que ==
fizesse o que faria, ficaria mais ou menos assim:
function isEqual(x, y) { // if `==` were a function
if(typeof y === typeof x) return y === x;
// treat null and undefined the same
var xIsNothing = (y === undefined) || (y === null);
var yIsNothing = (x === undefined) || (x === null);
if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);
if(typeof y === "function" || typeof x === "function") {
// if either value is a string
// convert the function into a string and compare
if(typeof x === "string") {
return x === y.toString();
} else if(typeof y === "string") {
return x.toString() === y;
}
return false;
}
if(typeof x === "object") x = toPrimitive(x);
if(typeof y === "object") y = toPrimitive(y);
if(typeof y === typeof x) return y === x;
// convert x and y into numbers if they are not already use the "+" trick
if(typeof x !== "number") x = +x;
if(typeof y !== "number") y = +y;
// actually the real `==` is even more complicated than this, especially in ES6
return x === y;
}
function toPrimitive(obj) {
var value = obj.valueOf();
if(obj !== value) return value;
return obj.toString();
}
Então o que isso quer dizer?
Isso significa que ==
é complicado.
Por ser complicado, é difícil saber o que acontecerá quando você o usar.
O que significa que você pode acabar com bugs.
Portanto, a moral da história é ...
Torne sua vida menos complicada.
Use em ===
vez de ==
.
O fim.
===
verifica os mesmos lados são iguais em tipo e valor .
Exemplo:
'1' === 1 // will return "false" because `string` is not a `number`
Exemplo comum:
0 == '' // will be "true", but it's very common to want this check to be "false"
Outro exemplo comum:
null == undefined // returns "true", but in most cases a distinction is necessary
Muitas vezes um untyped cheque seria útil porque você não se importa se o valor é ou undefined
, null
, 0
ou""
Diagrama de fluxo de execução de Javascript para igualdade estrita / comparação '==='
Diagrama de fluxo de execução de Javascript para comparação / igualdade não estrita '=='
JavaScript ===
vs ==
.
0==false // true
0===false // false, because they are of a different type
1=="1" // true, auto type coercion
1==="1" // false, because they are of a different type
Significa igualdade sem coerção de tipo coerção de tipo significa que o JavaScript não converte automaticamente nenhum outro tipo de dados em tipos de dados de string
0==false // true,although they are different types
0===false // false,as they are different types
2=='2' //true,different types,one is string and another is integer but
javaScript convert 2 to string by using == operator
2==='2' //false because by using === operator ,javaScript do not convert
integer to string
2===2 //true because both have same value and same types
Em um script típico, não haverá diferença de desempenho. Mais importante pode ser o fato de que mil "===" é 1 KB mais pesado do que mil "==" :) Os criadores de perfil de JavaScript podem dizer se há uma diferença de desempenho no seu caso.
Mas pessoalmente eu faria o que o JSLint sugere. Essa recomendação não existe por causa de problemas de desempenho, mas porque os meios de coerção de tipo ('\t\r\n' == 0)
são verdadeiros.
O operador de comparação igual == é confuso e deve ser evitado.
Se você TEM QUE viver com isso, lembre-se das três coisas a seguir:
- Não é transitivo: (a == b) e (b == c) não leva a (a == c)
- É mutuamente exclusivo para sua negação: (a == b) e (a! = B) sempre mantêm valores booleanos opostos, com todos os a e b.
- Em caso de dúvida, aprenda de cor a seguinte tabela de verdade:
TABELA DE VERDADE DO OPERADOR IGUAL EM JAVASCRIPT
- Cada linha da tabela é um conjunto de 3 valores mutuamente "iguais", o que significa que quaisquer 2 valores entre eles são iguais usando o sinal de igual == *
** ESTRANHO: observe que quaisquer dois valores na primeira coluna não são iguais nesse sentido. **
'' == 0 == false // Any two values among these 3 ones are equal with the == operator
'0' == 0 == false // Also a set of 3 equal values, note that only 0 and false are repeated
'\t' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
null == undefined // These two "default" values are not-equal to any of the listed values above
NaN // NaN is not equal to any thing, even to itself.
É improvável que haja qualquer diferença de desempenho entre as duas operações em seu uso. Não há conversão de tipo a ser feita porque os dois parâmetros já são do mesmo tipo. Ambas as operações terão uma comparação de tipo seguida por uma comparação de valor.
Sim! Isto é importante.
===
operador em javascript verifica o valor, bem como o tipo, em que o ==
operador apenas verifica o valor (faz a conversão de tipo, se necessário) .
Você pode testá-lo facilmente. Cole o código a seguir em um arquivo HTML e abra-o no navegador
<script>
function onPageLoad()
{
var x = "5";
var y = 5;
alert(x === 5);
};
</script>
</head>
<body onload='onPageLoad();'>
Você obterá ' falso ' em alerta. Agora modifique o onPageLoad()
método para alert(x == 5);
que se torne verdadeiro .
===
operador verifica os valores, bem como os tipos das variáveis de igualdade.
==
operador apenas verifica o valor das variáveis de igualdade.
É um teste de verificação rigoroso.
É uma coisa boa, especialmente se você estiver verificando entre 0 e falso e nulo.
Por exemplo, se você tem:
$a = 0;
Então:
$a==0;
$a==NULL; $a==false;
Tudo retorna verdadeiro e você pode não querer isso. Vamos supor que você tenha uma função que pode retornar o 0º índice de uma matriz ou falso em caso de falha. Se você marcar com "==" falso, poderá obter um resultado confuso.
Então, com a mesma coisa acima, mas um teste rigoroso:
$a = 0; $a===0; // returns true
$a===NULL; // returns false $a===false; // returns false
O JSLint às vezes oferece razões irreais para modificar coisas. ===
tem exatamente o mesmo desempenho como ==
se os tipos já fossem os mesmos.
É mais rápido apenas quando os tipos não são os mesmos; nesse caso, ele não tenta converter os tipos, mas retorna diretamente um falso.
Então, IMHO, JSLint podem ser usados para escrever novos códigos, mas a superotimização inútil deve ser evitada a todo custo.
Ou seja, não há razão para mudar ==
para ===
em uma verificação como if (a == 'test')
quando você sabe que a só pode ser uma String.
Modificar muito código dessa maneira desperdiça o tempo dos desenvolvedores e revisores e não leva a nada.
Simplesmente
==
significa comparação entre operandos com type conversion
E
===
significa comparação entre operandos sem type conversion
A conversão de tipo em javaScript significa que o javaScript converte automaticamente quaisquer outros tipos de dados em tipos de dados de string.
Por exemplo:
123=='123' //will return true, because JS convert integer 123 to string '123'
//as we used '==' operator
123==='123' //will return false, because JS do not convert integer 123 to string
//'123' as we used '===' operator
Um exemplo simples é
2 == '2' -> true, values are SAME because of type conversion.
2 === '2' -> false, values are NOT SAME because of no type conversion.
Como regra geral, eu geralmente usaria em ===
vez de ==
(e em !==
vez de !=
).
As razões são explicadas nas respostas acima e também Douglas Crockford é bastante claro sobre isso ( JavaScript: as partes boas ).
No entanto, há uma única exceção : == null
é uma maneira eficiente de verificar se 'é nulo ou indefinido':
if( value == null ){
// value is either null or undefined
}
Por exemplo, o jQuery 1.9.1 usa esse padrão 43 vezes, e o verificador de sintaxe JSHint ainda fornece a eqnull
opção relaxante por esse motivo.
Do guia de estilo jQuery :
Verificações estritas de igualdade (===) devem ser usadas em favor de ==. A única exceção é ao verificar se há indefinido e nulo por meio de nulo.
// Check for both undefined and null values, for some important reason. undefOrNull == null;
As 2 primeiras respostas mencionadas == significa igualdade e === significa identidade. Infelizmente, esta afirmação está incorreta.
Se ambos os operandos de == forem objetos, eles serão comparados para ver se são o mesmo objeto. Se ambos os operandos apontam para o mesmo objeto, o operador igual retorna verdadeiro. Caso contrário, os dois não são iguais.
var a = [1, 2, 3];
var b = [1, 2, 3];
console.log(a == b) // false
console.log(a === b) // false
No código acima, == e === são falsos porque aeb não são os mesmos objetos.
Isso quer dizer: se ambos os operandos de == são objetos, == se comporta da mesma forma que ===, que também significa identidade. A diferença essencial entre esses dois operadores é a conversão de tipo. == tem conversão antes de verificar a igualdade, mas === não.
O problema é que você pode facilmente ter problemas, já que o JavaScript tem muitos significados de conversões implícitas ...
var x = 0;
var isTrue = x == null;
var isFalse = x === null;
O que logo se torna um problema. O melhor exemplo de por que a conversão implícita é "má" pode ser obtido a partir deste código em MFC / C ++ que, na verdade, será compilado devido a uma conversão implícita de CString para HANDLE, que é um tipo de typedef de ponteiro ...
CString x;
delete x;
O que obviamente durante o tempo de execução faz coisas muito indefinidas ...
Google para conversões implícitas em C ++ e STL para obter alguns dos argumentos contra isso ...
Da referência principal do javascript
===
Retornatrue
se os operandos são estritamente iguais (veja acima) sem conversão de tipo.
Comparação de igualdade:
Operador ==
Retorna verdadeiro, quando ambos os operandos são iguais. Os operandos são convertidos para o mesmo tipo antes de serem comparados.
>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true
Igualdade e comparação de tipo:
Operador ===
Retorna verdadeiro se ambos os operandos forem iguais e do mesmo tipo. Geralmente é melhor e mais seguro se você comparar dessa forma, porque não há conversões de tipo nos bastidores.
>>> 1 === '1'
false
>>> 1 === 1
true
Aqui está uma tabela de comparação útil que mostra as conversões que acontecem e as diferenças entre ==
e ===
.
Como afirma a conclusão:
"Use três iguais, a menos que você entenda completamente as conversões que ocorrem para dois iguais."
http://dorey.github.io/JavaScript-Equality-Table/
nulos e indefinidos são nada, ou seja,
var a;
var b = null;
Aqui a
e b
não tem valores. Considerando que, 0, falso e '' são todos valores. Uma coisa comum entre todos esses é que são todos valores falsos, o que significa que todos eles satisfazem condições falsas.
Portanto, o 0, falso e '' juntos formam um subgrupo. E, por outro lado, nulo e indefinido formam o segundo subgrupo. Confira as comparações na imagem abaixo. null e undefined seriam iguais. Os outros três seriam iguais. Mas, todos eles são tratados como condições falsas em JavaScript.
Isso é igual a qualquer objeto (como {}, matrizes, etc.), string não vazia e Boolean true são todas condições verdadeiras. Mas, eles não são todos iguais.