node Qual operador de igual(== vs===) deve ser usado em comparações de JavaScript?




|| node js (20)

Estou usando o JSLint para percorrer o JavaScript, e ele está retornando muitas sugestões para substituir == (dois sinais de igual) com === (três sinais de igual) ao fazer coisas como comparar idSele_UNVEHtype.value.length == 0 dentro de um if declaração.

Existe um benefício de desempenho para substituir == por === ?

Qualquer melhoria de desempenho seria bem-vinda, já que existem muitos operadores de comparação.

Se nenhuma conversão de tipo ocorrer, haverá um ganho de desempenho em relação a == ?

https://code.i-harness.com


É improvável que haja qualquer diferença de desempenho entre as duas operações no 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.


Deixe-me adicionar este conselho:

Em caso de dúvida, leia a specification !

ECMA-262 é a especificação para 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 o novo String ("a")! == "a" .

Por favor, deixe-me explicar como ler a especificação para esclarecer esta questão. Eu vejo que neste tópico muito antigo ninguém tinha uma resposta para o efeito muito estranho. Então, se você puder ler uma especificação, isso o ajudará tremendamente em sua profissão. É uma habilidade adquirida. Então, vamos continuar.

A pesquisa no arquivo PDF por === me leva à página 56 da especificação: 11.9.4. O operador Strict Equals (===) , e depois de percorrer o specificationalese eu acho:

11.9.6 O algoritmo de comparação de igualdade estrita
A comparação x === y, onde x e y são valores, produz true ou false . Tal comparação é realizada da seguinte forma:
1. Se Type (x) for diferente de Type (y), retorne false .
2. Se Type (x) for indefinido, retorne true .
3. Se o Tipo (x) for Nulo, retorne verdadeiro .
4. Se Type (x) não for Number, vá para a etapa 11.
5. Se x for NaN , retorne false .
6. Se y for NaN , retorne false .
7. Se x for o mesmo valor numérico de y, retorne true .
8. Se x for +0 e y for −0, retorne verdadeiro .
9. Se x for −0 e y for +0, retorne verdadeiro .
10. Retorne falso .
11. Se Type (x) for String, então retorne true se xey forem exatamente a mesma seqüência de caracteres (mesmo comprimento e mesmos caracteres nas posições correspondentes); Caso contrário, retorne false .
12. Se Type (x) for booleano, retorne true se x e y forem ambos verdadeiros ou ambos falsos ; Caso contrário, retorne false .
13. Retorna verdadeiro se xey se referir ao mesmo objeto ou se eles se referirem a objetos unidos entre si (ver 13.1.2). Caso contrário, retorne falso .

Interessante é o passo 11. Sim, as strings são tratadas como tipos de valor. Mas isso não explica porque o novo String ("a")! == "a" . Temos um navegador que não está em conformidade com o ECMA-262?

Não tão rápido!

Vamos verificar os tipos dos operandos. Experimente você mesmo, envolvendo-os em typeof () . Eu acho que new String ("a") é um objeto, e a etapa 1 é usada: return false se os tipos forem diferentes.

Se você quer saber por que o novo String ("a") não retorna uma string, que tal um exercício lendo uma especificação? Diverta-se!

Aidiakapi escreveu isto em um comentário abaixo:

A partir da especificação

11.2.2 O novo Operador :

Se Type (construtor) não for Object, lance uma exceção TypeError.

Com outras palavras, se String não fosse do tipo Object, não poderia ser usado com o novo operador.

new sempre retorna um Object, mesmo para os construtores String , também. E ai! A semântica do valor para strings (consulte a etapa 11) é perdida.

E isso finalmente significa: new String ("a")! == "a" .


Ele verifica se 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

Em JavaScript, significa o mesmo valor e tipo.

Por exemplo,

4 == "4" // will return true

mas

4 === "4" // will return false 

Em um roteiro 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 profilers JavaScript podem dizer se existe uma diferença de desempenho no seu caso.

Mas pessoalmente eu faria o que o JSLint sugere. Esta recomendação não está lá por causa de problemas de desempenho, mas porque meios de coerção de tipo ('\t\r\n' == 0) são verdadeiros.


Eu testei isso no Firefox com o Firebug usando 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 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 é um motivo para fazer === . Digite segurança (bem, tão seguro quanto você vai entrar em JavaScript), e a qualidade do código é.


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

Nas respostas aqui, eu não li nada sobre o que significa igualdade . 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, possuem 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 até mesmo:

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. Há mais na história do que ser igual e ser do mesmo tipo.

A regra é:

Para tipos de valor (números):
a === b retorna verdadeiro se a e b tiverem o mesmo valor e forem do mesmo tipo

Para tipos de referência:
a === b retorna verdadeiro se a e b referência exatamente ao mesmo objeto

Para strings:
a === b retorna verdadeiro se a e b forem ambos strings e contiverem exatamente os mesmos caracteres

Cordas: o caso especial ...

Strings não são tipos de valor, mas em Javascript eles se comportam como tipos de valor, então eles serão "iguais" quando os caracteres na string forem os mesmos e quando forem do mesmo tamanho (como 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 cordas se comportam como tipos de valor? Bem, depende de quem você pergunta ... Neste caso, a e b não são do mesmo tipo. a é do tipo Object , enquanto b é do tipo string . Apenas lembre-se de que criar um objeto string usando o construtor String cria algo do tipo Object que se comporta como uma string na maior parte do tempo .


O operador de identidade ( === ) se comporta de maneira idêntica ao operador de igualdade ( == ), exceto que nenhuma conversão de tipo é feita e os tipos devem ser os mesmos para serem considerados iguais.

Referência: Javascript Tutorial: Comparison Operators

O operador == irá comparar a igualdade depois de 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 do mal == e != . Os bons funcionam da maneira que você esperaria. Se os dois operandos forem do mesmo tipo e tiverem o mesmo valor, então === produzirá true e !== produzirá false . Os gêmeos maus fazem a coisa certa quando os operandos são do mesmo tipo, mas se eles são de tipos diferentes, eles tentam coagir os valores. as regras pelas quais eles fazem isso são complicadas e memorá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, use sempre === e !== . Todas as comparações mostradas apenas geram false com o operador === .

Atualizar:

Um bom ponto foi trazido pelo @Casebash nos comentários e na answer @Phillipe Laybaert aos tipos de referência. Para tipos de referência == e === agem consistentemente uns com os outros (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 um literal com um objeto que avalia o mesmo literal, devido ao seu toString ou valueOf . Por exemplo, considere a comparação de uma string literal com um objeto de string criado pelo construtor String .

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Aqui o operador == está verificando os valores dos dois objetos e retornando true , mas o === está vendo que eles não são do mesmo tipo e retornando false . Qual deles está correto? Isso realmente depende do que você está tentando comparar. Meu conselho é ignorar completamente a questão e simplesmente não use o construtor String para criar objetos string.

Referência
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3


Uma interessante representação pictórica da comparação de igualdade entre == e === .

Fonte: dorey.github.io/JavaScript-Equality-Table

var1 === var2

Ao usar === para testes de igualdade JavaScript, tudo é como está. Nada é convertido antes de ser avaliado.

var1 == var2

Ao usar == para testes de igualdade de JavaScript, algumas conversões de funky acontecem.

Moral da história:

Use === menos que você entenda totalmente as conversões que ocorrem com == .


É um teste de verificação rigoroso.

É uma coisa boa, especialmente se você está verificando entre 0 e falso e nulo.

Por exemplo, se você tiver:

$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 possa retornar o 0º índice de uma matriz ou falsa na falha. Se você marcar com "==" false, 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

Comparação de igualdade:

Operador ==

Retorna true, quando os dois 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 tipos:

Operador ===

Retorna true se ambos os operandos forem iguais e do mesmo tipo. Em geral, é melhor e mais seguro se você comparar dessa maneira, porque não há conversões de tipo por trás das cenas.

>>> 1 === '1'
false
>>> 1 === 1
true

O operador de comparação igual == é confuso e deve ser evitado.

Se você tem que viver com isso, então lembre-se das seguintes 3 coisas:

  1. Não é transitivo: (a == b) e (b == c) não leva a (a == c)
  2. É mutuamente exclusivo à sua negação: (a == b) e (a! = B) sempre mantêm valores booleanos opostos, com todos aeb.
  3. Em caso de dúvida, aprenda de cor a seguinte tabela de verdade:

TABELA DE VERDADE DE OPERADOR IGUAL EM JAVASCRIPT

  • Cada linha na tabela é um conjunto de 3 valores mutuamente "iguais", o que significa que quaisquer 2 valores entre eles são iguais usando o sinal igual == *

** STRANGE: 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.

Por que é tão imprevisível?

O que você ganha quando compara uma string vazia "" com o número zero 0 ?

true

Sim, isso é certo de acordo com == uma seqüência vazia e o número zero são o 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 isso de novo:

(A == B) && (B == C) // true
(A == C) // **FALSE**

E isso é apenas o material maluco que você começa com primitivos.

É um novo nível de loucura quando você usa == com objetos.

Neste momento 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 os mesmos.

== faz um monte de outras coisas .

Tem tratamento especial para funções, tratamento especial para nulos, indefinido, strings, o nome dele.

Isso é muito maluco.

De fato, se você tentou escrever uma função que faz o que == seria algo como isto:

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.

Porque é complicado, é difícil saber o que vai acontecer quando você usá-lo.

O que significa que você pode acabar com bugs.

Então a moral da história é ...

Torne sua vida menos complicada.

Use === vez de == .

O fim.


O problema é que você pode facilmente ter problemas, pois o JavaScript tem muitas conversões implícitas, o que significa ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Que logo se torna um problema. A melhor amostra de por que a conversão implícita é "maligna" pode ser obtida deste código no MFC / C ++ que, na verdade, será compilado devido a uma conversão implícita de CString para HANDLE, que é um tipo typedef de ponteiro ...

CString x;
delete x;

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 ...


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 

nulo e indefinido são nada, isto é,

var a;
var b = null;

Aqui ae bnão tem valores. Considerando que, 0, falso e '' são todos os valores. Uma coisa comum entre todos estes é que eles são todos valores falsos, o que significa que todos eles satisfazem condições falsas.

Então, o 0, falso e '' juntos formam um subgrupo. E por outro lado, null e undefined formam o segundo subgrupo. Verifique as comparações na imagem abaixo. null e indefinido seria igual. Os outros três seriam iguais entre si. Mas todos eles são tratados como falsas condições em JavaScript.

Isso é o mesmo que qualquer objeto (como {}, matrizes, etc.), string não vazia e true booleano são todas as condições verdadeiras. Mas todos eles não são iguais.


* Operadores === vs == *

1 == true    =>    true
true == true    =>    true
1 === true    =>    false
true === true    =>    true

Como regra geral, eu usaria geralmente em ===vez de ==(e em !==vez de !=).

Razões são explicadas nas respostas acima e também Douglas Crockford é bastante claro sobre isso ( JavaScript: The Good Parts ).

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 do JSHint também fornece a eqnullopção relaxante por esse motivo.

Do guia de estilo do jQuery :

Verificações estritas de igualdade (===) devem ser usadas em favor de ==. A única exceção é ao verificar undefined e null por meio de null.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;

O JSLint às vezes lhe dá razões irreais para modificar o material. ===tem exatamente o mesmo desempenho como ==se os tipos já fossem os mesmos.

Só é mais rápido quando os tipos não são os mesmos e, nesse caso, não tenta converter tipos, mas retorna diretamente um falso.

Então, IMHO, o JSLint talvez seja usado para escrever código novo, mas a otimização excessiva inútil deve ser evitada a todo custo.

Ou seja, não há razão para mudar ==para ===um cheque como if (a == 'test')quando você sabe que um só pode ser uma String.

Modificar muito código dessa maneira desperdiça tempo dos desenvolvedores e revisores e não alcança nada.





identity-operator