Desmistificando o operador de igual duplo em JavaScript
Não é tão assustador quanto dizem, e pode ser seu amigo
O operador double-equals do JavaScript, ==, tornou-se um bicho-papão entre os desenvolvedores, tanto dentro quanto fora da comunidade. Isso ocorre porque, historicamente, o double-equals teve as chamadas peculiaridades que, em alguns casos, o levam a fazer coisas inesperadas. Muitas pessoas, e as ferramentas que eles fazem, querem que você sele o operador em um caixão de chumbo e o enterre milhares de metros abaixo do solo ou atire-o no espaço em direção a Plutão. E com muita confiança também! Mas inesperado não é o mesmo que errático, peculiar, etc. Significa apenas que você não tinha as expectativas certas sobre como realmente funciona .
Este artigo tentará ajudá-lo a entender como esse operador funciona e mostrar exemplos de onde ele é realmente útil. Existem razões legítimas para usar esse operador e, desde que você saiba quando e como pode ou não usá-lo, não há absolutamente nada de errado com ele. No processo, espero ajudá-lo a ver que os medos podem ser superados com conhecimento e que o conhecimento abre novas portas que, de outra forma, permaneceriam fechadas para você para sempre.
Nota : tudo o que estamos prestes a dizer ==se aplica !=também.
As “peculiaridades”
Vamos primeiro ver as chamadas peculiaridades que esse operador possui. Aqui estão algumas das coisas que você pode não esperar que funcionem:
[] == 0 // true
[] == '' // true
[] == ![] // true
'1' == 1 // true
({foo: 'bar'}) == '[object Object]' // true
new Date(0) == 'Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)' // true
null == undefined // true
(Se você quiser aproveitar a magia e/ou continuar tirando sarro do idioma, pare de ler agora e vá embora. Não deixe que eu estrague sua diversão.)
Como o duplo-igual realmente funciona
O operador double-equal força um de seus operandos se eles não forem do mesmo tipo. Por exemplo, se um operando for uma string e o outro for um número, ele converte a string em um número e tenta novamente.
O processo exato é o seguinte:
- Se ambos os operandos forem do mesmo tipo, retorna o resultado de
===. - Se ambos os operandos forem
undefinedounullentão retornetrue. - Se um operando for um número e o outro uma string, converta a string em um número e reinicie a comparação.
- Se um dos operandos for um booleano, converta o booleano em um número (
0forfalse,1fortrue) e reinicie a comparação. - Se um lado for um objeto (incluindo uma matriz) e o outro lado for um número, string ou símbolo, o objeto será convertido em um primitivo tentando primeiro o
valueOf()e depoistoString(), o que retornar primeiro um valor primitivo e reinicie a comparação . - Se nenhuma das opções acima se aplicar, retorne
false.
- O lado esquerdo é uma matriz; o lado direito é um número, então chame
valueOf()o array. - Como
valueOf()retorna o mesmo array, chametoString(). - Isso nos dá uma string vazia. Recomeçar.
- Agora estamos comparando
'' == 0. - O lado esquerdo é uma string e o lado direito é um número, então convertemos a string em um número (o mesmo que
Number('')). - Isso nos dá
0. Recomeçar. - Agora estamos comparando
0 == 0. - Como os dois lados são do mesmo tipo (número), fazemos
0 === 0qual étrue.
Ai está. Não é mais tão mágico. Também não é extremamente útil, claro, mas também não é um bug. O importante a lembrar é que sempre funciona da mesma maneira. Não é uma peculiaridade imprevisível. É apenas um algoritmo (ligeiramente) complicado em alguns casos.
O Dateobjeto é uma exceção. Eles são sempre coagidos em uma string.
new Date(0).valueOf() === 0 // true
new Date(0) == 0 // false; because it did not actually call valueOf()
Como isso me ajuda?
Em primeiro lugar, você pode passar nessas entrevistas. Se você acabar tendo que responder a uma dessas perguntas, agora pode responder com confiança!
Em segundo lugar, agora você (espero) sabe como saber se algum uso de duplo-igual está correto ou não.
Mais importante, porém, há muitos motivos legítimos para usar o duplo igual precisamente porque ele coage os valores. Vamos dar uma olhada em alguns.
Comparando nulo ou indefinido
O uso aprovado pela comunidade — aquele que recebeu a bênção oficial do seu deus local do JavaScript — é o uso de duplo igual para testar se algum valor é nullou undefined. Os exemplos a seguir fazem o mesmo:
x == null
x == undefined // you can always use null as it's shorter and does the same
x === null || x === undefined
Comparando strings e números e booleanos
Métodos de nó DOM como getAttribute()ou propriedades como valuesempre retornam strings. Se você quiser comparar isso rapidamente com, digamos, um número, poderá usar o duplo igual sem converter manualmente a string em um número de vice-versa. Todos os itens a seguir alcançarão o mesmo:
someInput.value == 1
Number(someInput.value) === 1
someInput.value === '1'
someInput.value == true
Objetos com valueOf() e toString()
Se você implementar o valueOf()ou o toString()método em seus objetos ou tiver certeza de que eles o fazem em algum objeto, você pode, é claro, confiar nisso para testar os valores primitivos.
let STATUS_DONE = 0, STATUS_STARTED = 10, STATUS_ERROR = 100
class MyWorker {
constructor() {
this.status = STATUS_STARTED
}
valueOf() {
return this.status
}
}
let worker = new MyWorker()
worker == STATUS_STARTED // true
worker == '10' // true; (e.g., coming from an HTMLInputElement.value)
worker.status === STATUS_STARTED // true
Geralmente, você não deseja comparar objetos que não implementam um usável valueOf()ou toString()(incluindo matrizes) com outros valores usando duplos iguais.
Embora array == 0possa parecer uma maneira legal de testar matrizes vazias, é muito mais barato fazer apenas !array.length. Você certamente não pode dizer array == []. Isso não é uma coisa em JavaScript.
A única razão pela qual você compararia objetos simples e arrays com outros valores é para determinar a identidade — estamos falando de um único e mesmo objeto. Para este propósito, triplo-igual é a única opção.
outros casos
Tenho certeza de que existem outras maneiras de usar o duplo igual como um atalho para algumas coerções. Simplesmente mantendo a porta aberta - use um banquinho, não o pé, pois alguém da comunidade pode tentar fechá-la à força para você! — você pode descobrir formas criativas de usar isso.
Se você tem medo de que uma porta quebrada faça com que o vento o mate (vocês, eslavos, sabem do que estou falando !) Então, por favor, feche-a. Você está desculpado!
Coerção em todos os lugares
O principal medo dos iguais duplos vem da coerção mal compreendida, que às vezes pode ser bastante complicada de descobrir (embora, você realmente só precise descobrir uma vez, e então tudo ficará claro depois disso).
Mas o JavaScript está cheio de coerções! Por exemplo, tudo o que dissemos sobre os duplos iguais também se aplica a >, <, >=e <=. Todos eles coagem e também não há equivalentes triplos para eles! A única diferença entre os outros operadores de comparação de comparação e os duplos iguais (e !=) é que os outros operadores tratarão Dateobjetos como números, então você pode dizer myDate > myOtherDate.
Por exemplo, você sabia que pode dizer isso?
[2] > false // true
Math.max(-1, [2]) // 2
let yesno = ['no', 'yes']
yesno[true] // 'yes'
yesno[false] // 'no'
new Date('2023', 0, 1).getFullYear() // 2023
Se você mantiver seu juízo sobre você, não é muito provável que você se depare com um caso em que isso realmente exploda na sua cara. As pessoas usam esses métodos e operadores o tempo todo, e você não ouve alguma ferramenta ou sinalização de tolo Math.max()ou <. Não há absolutamente nenhuma razão para ==ser diferente do que algum medo irracional de algoritmo de coerção mal compreendido.
Impacto no desempenho
Se você vir algum benchmark em que o triplo-igual supera o duplo-igual, verifique se a versão do triplo-igual realmente executa qualquer conversão de tipo explícita. Se não, provavelmente é trapaça.
Se estivermos usando duplo igual para realizar coerção e comparação de uma só vez, ou comparando valores do mesmo tipo, não deve haver impacto significativo no desempenho em comparação com uma solução equivalente que usa triplo igual.
As seguintes operações são praticamente as mesmas em termos de desempenho:
input.value == 1
Number(input.value) === 1
Como sempre, depende inteiramente de você. Mais uma vez um lembrete, você tem usado <, >e outros operadores e espero que não tenha matado muito ninguém, matou.
Vejo gente que quase nunca usa, e também quem quase nunca usa triplo igual. (Enfatizado “quase” para que não haja confusão com “definitivamente nunca”, pois não existe tal coisa.) O código funciona muito bem em ambos os casos (apenas um pouco diferente — coerção de tipo versus conversão de tipo).
Evitá -lo dói ou tem alguma desvantagem não óbvia? Na verdade, não. Você terá que fazer um pouco mais de conversão de tipo do que o necessário, mas não consigo pensar em mais nada. Eu usei igual a triplo na maior parte da minha carreira e realmente não doeu.
Só não seja esse cara:
// Oooh, look, error from ESLint... what an amateur, haha!
if (this.dataset.direction == UP) this.sortAsc()
// ^^-- ESLINT ERROR //
// I'll fix it r/q
if (this.dataset.direction === UP) this.sortAsc()
// ESLINT BE LIKE //





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)