Introdução: O problema que explodiu o Stack Overflow
\n\nImagine a situação: você está em uma entrevista, e o entrevistador, com um sorriso malicioso, pergunta: «A expressão a == 1 && a == 2 && a == 3 pode alguma vez retornar true?». A primeira reação é «Claro que não! Uma variável não pode ser igual a três números diferentes ao mesmo tempo».
No entanto, se você conhece o JavaScript um pouco mais a fundo, sabe que nesta linguagem são possíveis as coisas mais inesperadas. Esta pergunta acumulou milhares de visualizações no Stack Overflow e se tornou um clássico para testar a compreensão de coerção de tipos, getters e wrappers de objetos em JS.
\n\nNeste artigo, não apenas provaremos que isso é possível, mas também analisaremos 5 maneiras diferentes de fazer com que (a==1 && a==2 && a==3) retorne true. Você aprenderá como funciona a comparação não estrita (==), como ela difere da estrita (===) e como podemos manipulá-la.
O artigo será útil tanto para iniciantes que desejam entender mais profundamente o JavaScript, quanto para desenvolvedores experientes que estão se preparando para uma entrevista. Vamos nessa!
\n\nMétodo nº1: A mágica do valueOf (o mais popular)
\n\nA maneira mais elegante e frequentemente citada é usar um objeto personalizado com o método valueOf sobrescrito. Em JavaScript, quando você compara um objeto com um primitivo usando ==, o motor automaticamente chama valueOf() (ou toString()) para converter o objeto em primitivo.
Criaremos um objeto contador que, a cada chamada de valueOf, incrementa seu valor em 1.
const a = {\n value: 1,\n valueOf() {\n return this.value++;\n }\n};\n\nconsole.log(a == 1 && a == 2 && a == 3); // true\n\nComo funciona:
\n- \n
- Na primeira comparação
a == 1,valueOf()é chamado, retorna 1 evalueé incrementado para 2. \n - Na segunda comparação
a == 2,valueOf()é chamado novamente, retorna 2 evaluese torna 3. \n - A terceira comparação
a == 3completa a cadeia com sucesso. \n
Este é um exemplo perfeito de type coercion (coerção forçada de tipos) em ação. É exatamente esse mecanismo que torna o JavaScript uma linguagem ao mesmo tempo flexível e perigosa.
\n\nMétodo nº2: toString — o gêmeo do valueOf
\n\nSe você sobrescrever toString em vez de valueOf, o resultado será o mesmo. O JavaScript na comparação não estrita pode usar qualquer um desses métodos para converter o objeto.
const a = {\n value: 1,\n toString() {\n return this.value++;\n }\n};\n\nconsole.log(a == 1 && a == 2 && a == 3); // true\n\nA diferença é sutil: valueOf tem prioridade para comparações numéricas, enquanto toString tem para comparações de string. Mas no nosso caso, ambos funcionam perfeitamente.
Método nº3: Getters no escopo global
\n\nMuitos nem suspeitam que as variáveis globais em JavaScript são, na verdade, propriedades do objeto global (window no navegador, global no Node.js). E as propriedades podem ser definidas através de getters.
Podemos definir um getter para a variável a diretamente no objeto global:
let value = 1;\nObject.defineProperty(window, 'a', {\n get() {\n return value++;\n }\n});\n\nconsole.log(a == 1 && a == 2 && a == 3); // true\n\nEste método é particularmente interessante porque a se comporta como uma variável comum, embora na verdade seja uma propriedade com getter. Cada vez que você acessa a, o getter retorna um novo valor.
Blogs
Book Recommendations
Leia também
Programação de Rede em TypeScript: de Sockets a WebSocket
Como conseguir um emprego como desenvolvedor Java: dicas e currículo na prática
Swift no mundo do hardware: escrevendo código para microcontroladores
CI/CD para projetos Kotlin: GitHub Actions do A ao Z
Cliente HTTP em Rust: fazendo requisições corretamente do A ao Z