JSLint esperado '===' e em vez disso vi '=='

90

Recentemente, eu estava executando parte do meu código por meio de JSLint quando encontrei esse erro. O que eu acho engraçado sobre esse erro, porém, é que ele assume automaticamente que todos == deveriam ser ===.

Isso realmente faz algum sentido? Eu pude ver muitos casos em que você não gostaria de comparar o tipo e estou preocupado que isso possa realmente causar problemas.

A palavra "Esperado" implicaria que isso deve ser feito TODAS as vezes ... Isso é o que não faz sentido para mim.

Metrópole
fonte
7
Também encontrei isso com JSLint. Fiz uma atualização de == para === e realmente quebrou o código que funcionava anteriormente.
kemiller2002
5
Se seu código tiver mais de 100 linhas, ele não passará jslint, realmente, é impossível.
3
"Quebrou" é uma palavra muito forte. Isso mudou o significado do seu código. Se você estava fazendo uma myVar == nullverificação, sim, grandes mudanças. ; ^) O argumento de Crockford é que tornou o significado do código mais preciso, e isso é difícil de argumentar.
ruffin de

Respostas:

127

IMO, usar cegamente ===, sem tentar entender como funciona a conversão de tipo , não faz muito sentido.

O principal medo sobre o operador Equals ==é que as regras de comparação, dependendo dos tipos comparados, podem tornar o operador não transitivo, por exemplo, se:

A == B AND
B == C

Realmente não garante que:

A == C

Por exemplo:

'0' == 0;   // true
 0  == '';  // true
'0' == '';  // false

O operador Strict Equals ===não é realmente necessário quando você compara valores do mesmo tipo, o exemplo mais comum:

if (typeof foo == "function") {
  //..
}

Comparamos o resultado do typeofoperador, que é sempre uma string , com um literal de string ...

Ou quando você conhece as regras de coerção de tipo, por exemplo, verifique se algo é nullou undefinedalgo:

if (foo == null) {
  // foo is null or undefined
}

// Vs. the following non-sense version:

if (foo === null || typeof foo === "undefined") {
  // foo is null or undefined
}
Christian C. Salvadó
fonte
1
Eu odeio essa regra do JSLint. Acho que o verdadeiro problema é que as pessoas não devem usar os operadores de maneiras que não entendam (ironicamente, muitas vezes são o mesmo tipo de pessoa que substituiria cegamente '===' por '=='). Claro, existem alguns casos comuns que surgem ao comparar o número 0 com várias strings, mas se você estiver comparando dados não relacionados como 0 == 'isto é uma string' - Seu código provavelmente tem problemas maiores do que duplo igual! Se você sabe com certeza com quais tipos está lidando e sabe exatamente como eles interagem com ==, acho que você deve usá-lo.
Jon
3
@Jon O objetivo do ===operador é a clareza do código. Não existe uma situação razoável a ser usada ==, pois nunca será tão clara e compreensível quanto o operador de identidade. Não se trata de entender os operadores ou não, mas de usar aquele que torna seu código mais legível e quase sem custo. Os únicos desenvolvedores que estão argumentando contra o operador de identidade são desenvolvedores solo e pessoas que não trabalham em equipes. Por definição, pessoas cujo código não é revisado por olhos suficientes.
Alternatex
2
Acho que a comparação == null é quase essencial. O problema se torna ainda menos importante se seu código for bem testado.
Jon
1
De fato, há momentos em que usar == é essencial para realizar o teste necessário. se foo.toString () for executado de maneira previsível e uma string simples precisar ser testada contra essa saída, escrever foo == stringToTest é muito mais limpo do que foo.toString () === stringToTest.
Crispen Smith
2
@Alternatex Se o ponto era clareza, eles não deveriam ter tornado TRIPLO igual a! Nenhum iniciante entende isso. Pelo menos double equals é conhecido em outras línguas. Além disso, there is no reasonable situationé uma distorção grosseira. Pense nos tipos de Javascript (nativos) Numbere String. Sua existência prova que os autores de Javascript tinham certos casos de uso em mente ==. Você realmente acha que new String('hi') === 'hi'avaliar falseé muito claro? Escreva um trecho de código que teste o argumento de sua função contra a 'hi'aceitação de String e string e me diga que está claro.
Stijn de Witt,
25

JSLint é inerentemente mais defensivo do que a sintaxe Javascript permite.

Da documentação JSLint:

Os operadores ==e !=fazem coerção de tipo antes de comparar. Isso é ruim porque faz ' \t\r\n' == 0com que seja verdade. Isso pode mascarar erros de tipo.

Ao comparar com qualquer um dos seguintes valores, use os operadores ===ou !==(que não fazem coerção de tipo):0 '' undefined null false true

Se você só se preocupam que um valor é truthy ou Falsas , então use o pequeno formulário. Ao invés de

(foo != 0)

apenas diga

(foo)

e em vez de

(foo == 0)

dizer

(!foo)

Os operadores ===e !==são os preferidos.

Daniel Vandersluis
fonte
8
Tenho que concluir que o pessoal da JSLint está trabalhando em uma torre de marfim muito alta da qual eles nunca saem. Javascript foi projetado para ser usado com o ==operador. O ===é um caso especial ... JSLint tenta fazer parecer que usando ==de alguma forma estar errado ... No entanto, tente o seguinte: var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}. Os tipos primitivos têm classes correspondentes que os substituem ( Number, String) e o Javascript depende do ==operador para torná-los naturais.
Stijn de Witt
17

Lembre-se de que o JSLint impõe a ideia de uma pessoa do que um bom JavaScript deve ser. Você ainda precisa usar o bom senso ao implementar as mudanças que ele sugere.

Em geral, comparar tipo e valor tornará seu código mais seguro (você não terá o comportamento inesperado quando a conversão de tipo não fizer o que você acha que deveria).

Justin Niessner
fonte
4
Além disso, não pode ser tão contextualizado quanto um programador. Funciona apenas porque a maioria dos usuários se atrapalha com a conversão automática de tipo inerente ao sistema (como violência - "ajuda, ajuda, estou sendo reprimido!")
Rudu
14

Triplo igual é diferente de duplo igual porque, além de verificar se os dois lados têm o mesmo valor, triplo igual também verifica se eles são do mesmo tipo de dados.

Então, ("4" == 4)é verdade, mas ("4" === 4)é falso.

Triplo-igual também é executado um pouco mais rápido, porque JavaScript não precisa perder tempo fazendo nenhuma conversão de tipo antes de fornecer a resposta.

JSLint visa deliberadamente tornar seu código JavaScript o mais estrito possível, com o objetivo de reduzir bugs obscuros. Ele destaca esse tipo de coisa para tentar fazer com que você codifique de uma forma que o force a respeitar os tipos de dados.

Mas o bom do JSLint é que ele é apenas um guia. Como dizem no site, vai magoar seus sentimentos, mesmo se você for um programador de JavaScript muito bom. Mas você não deve se sentir obrigado a seguir seus conselhos. Se você leu o que ele tem a dizer e o entende, mas tem certeza de que seu código não vai quebrar, então não há compulsão para mudar nada.

Você pode até mesmo dizer ao JSLint para ignorar categorias de verificações se não quiser ser bombardeado com avisos de que nada fará a respeito.

Spudley
fonte
3
Não perguntei "O que é ===", então não sei por que você respondeu.
Metrópolis
8
@Metropolis: se não por outro motivo, então como pano de fundo caso alguém leia a resposta que não saiba. Eu tentei responder sua pergunta nos parágrafos depois disso, no entanto.
Spudley de
@Spudley + 1 para informações adicionais e úteis
Ben Junior
1
sim, é 10-100 vezes mais rápido: teste de velocidade
jsperf
8

Uma citação de http://javascript.crockford.com/code.html :

=== e! == Operadores.

Quase sempre é melhor usar os operadores === e! ==. Os operadores == e! = Fazem coerção de tipo. Em particular, não use == para comparar com valores falsos.

JSLint é muito rígido, seu 'webjslint.js' nem passa pela sua própria validação.

Lekensteyn
fonte
Bom esclarecimento. Isso é verdade, sobre webjslint.jsnão validar - embora a maioria dos erros que vejo agora tenham a ver com espaçamento. Claramente, deve-se usar bom senso e julgamento razoável ao revisar JavaScript usando JSLint.
hotshot309
O uso da palavra alwaysdesqualifica automaticamente esta citação como sabedoria. Programadores inteligentes não são dogmáticos. Eles usam o que há de melhor em determinada situação. E eles acolhem e abraçam qualquer ferramenta embutida no núcleo da linguagem, não apenas descartando-a com um just never touch it. Resumindo: Meu código é mais curto (e não apenas para salvar um =caractere), portanto, meu site carrega mais rápido, com menor custo de largura de banda, portanto, meu usuário é melhor atendido.
Stijn de Witt
4

Se você quiser testar a falsidade. JSLint não permite

if (foo == null)

mas permite

if (!foo)
nano2nd
fonte
Use ===, que o JSLint recomenda.
clickbait
1
@NarawaGames Esta solução é perfeitamente aceitável.
Essa resposta não é boa. O fato é que ambos significam outra coisa. foo == nullverifica se há nulo ou indefinido. !fooverifica se há string nula, indefinida, 0 e vazia.
Markos
@Markos Esta resposta pretende ser uma alternativa útil para deixar o JSLint feliz e manter a lógica do código intacta, não para ser um equivalente exato. É por isso que prefixei a resposta com "Se estiver verificando se há falsidade"
nano2º de
3

Para ajudar a explicar esta questão e também explicar por que o NetBeans (de) 7.3 começou a mostrar este aviso, este é um extrato da resposta no rastreador de bug do NetBeans quando alguém relatou isso como um bug:

É uma boa prática usar === em vez de == em JavaScript.

Os operadores == e! = Fazem coerção de tipo antes de comparar. Isso é ruim porque faz com que '\ t \ r \ n' == 0 seja verdadeiro. Isso pode mascarar erros de tipo. O JSLint não pode determinar com segurança se == está sendo usado corretamente, então é melhor não usar == e! = De forma alguma e sempre usar os operadores === e! == mais confiáveis.

Referência

EM-Creations
fonte
1
Eu encontrei esse erro agora usando o Netbeans também. É estranho que eles tratassem isso com severidade de advertência devido ao caso bizarro de exemplo que forneceram.
volta de
1
quer dizer, é verdade, mas há muitos casos de uso em que a pessoa sabe que as duas coisas comparadas serão do mesmo tipo, então parece estranho que devido a este estranho caso em que um retorno de carro possa ser comparado ao número zero é a razão pela qual todos os usos de == são considerados errados. Estou descobrindo que === é mais rápido, já que nenhuma conversão de tipo é feita. Estou surpreso por não ter descoberto isso antes do netbeans.
chega em
@oMiKeY Sim, entendo o que você quer dizer, eles poderiam ter dado exemplos mais realistas!
EM-Creations
2

Bem, isso não pode realmente causar problemas, é apenas dar conselhos. É pegar ou largar. Dito isso, não tenho certeza de quão inteligente é. Pode muito bem haver contextos em que isso não apresente como um problema.

Rushyo
fonte
1
mas por que a palavra "Esperado" é usada? Isso faz parecer que você sempre deve fazer isso.
Metrópolis
4
O avaliador está procurando uma resposta válida, pois está tentando validá-la. Se não obtiver uma resposta válida, não é o que esperava. O validador parte do pressuposto de que está tudo bem e, a seguir, aponta os erros à medida que percorre o código. Ele não entende necessariamente o que é uma resposta inválida, apenas sabe quando vê uma não válida. Também pode funcionar ao contrário, procurando deliberadamente por códigos ruins de acordo com as regras do que é ruim. Whitelisting vs blacklisting.
Rushyo,
A pergunta era "Isso realmente faz algum sentido?". Dada essa pergunta, sim, é verdade. Além disso, foi há cinco anos . Jesus.
Rushyo