$cd~/artigos/equality-operators-igualdade-javascript
Fundamentals
série 33 Conceitos JS·parte 9 de 38

Equality Operators: `==` vs `===` — Como o JavaScript Realmente Compara Valores

12 minVanderlei José Alamino

Por que 1 == "1" retorna true, mas 1 === "1" retorna false? Por que typeof null retorna "object"? E por que NaN é o único valor em JavaScript que não é igual a si mesmo?

snippetJavaScript
// Mesmos valores, resultados diferentesconsole.log(1 == "1");   // true  — igualdade solta converte tiposconsole.log(1 === "1");  // false — igualdade estrita verifica tipo primeiro // Os quirks famososconsole.log(typeof null);  // "object" — um bug de 1995!console.log(NaN === NaN);  // false — NaN nunca é igual a nada

Entender os operadores de igualdade do JavaScript é crucial porque bugs de comparação estão entre os mais comuns no código JavaScript. Segundo a especificação ECMAScript (ECMA-262), o JavaScript define três algoritmos de igualdade distintos: Abstract Equality, Strict Equality e SameValue. Este guia vai te ensinar exatamente como ==, === e Object.is() funcionam, e quando usar cada um.

equality-operators-igualdade-javascript.meta.jsonjson

// metadados do artigo

{
  "tag": "fundamentos",
  "readTime": "12 min",
  "author": "Vanderlei José Alamino",
  "source": "33jsconcepts.com",
  "series": "33 Conceitos JS",
  "part": {
    "current": 9,
    "total": 38
  }
}
abrir fonte original
equality-operators-igualdade-javascript.mdmarkdown

Fonte de referência

Conteúdo adaptado a partir do guia original em inglês.

33jsconcepts.com
01

seção

Os Três Operadores de Igualdade: Visão Geral

O JavaScript oferece três formas de comparar valores quanto à igualdade. Aqui está o resumo rápido:

OperadorNomeCoerção de TipoMelhor Para
==Igualdade Solta (Abstract)SimVerificar null/undefined apenas
===Igualdade EstritaNãoEscolha padrão para tudo
Object.is()Igualdade Same-ValueNãoCasos extremos (NaN, ±0)
snippetJavaScript
// A mesma comparação, três resultados diferentesconst num = 1;const str = "1"; console.log(num == str);           // true  (coage string para número)console.log(num === str);          // false (tipos diferentes)console.log(Object.is(num, str));  // false (tipos diferentes)

A regra simples: use === para comparações. A única exceção: use == null para verificar se um valor está vazio (null ou undefined). Você raramente precisará de Object.is() — é para casos especiais que veremos mais adiante.

02

seção

O Professor Corrigindo Provas: Uma Analogia do Mundo Real

Imagine um professor corrigindo uma prova de matemática. A questão pergunta: "Quanto é 2 + 2?"

Um aluno escreve: 4 Outro aluno escreve: "4" (como texto) Um terceiro aluno escreve: 4.0

Quão rigoroso o professor deve ser na correção?

snippettext
        CORREÇÃO RELAXADA (==)              CORREÇÃO ESTRITA (===)      "A resposta está correta?"          "Está exatamente certa?"    ┌─────────────┐   ┌─────────────┐    ┌─────────────┐   ┌─────────────┐    │      4      │ = │    "4"      │    │      4      │ ≠ │    "4"      │    │  (number)   │   │  (string)   │    │  (number)   │   │  (string)   │    └─────────────┘   └─────────────┘    └─────────────┘   └─────────────┘          │                 │                  │                 │          └────────┬────────┘                  └────────┬────────┘                   ▼                                    ▼          "Perto o suficiente!" ✓                    "Tipos diferentes!" ✗

O JavaScript te dá ambos os tipos de professor:

  • Igualdade solta (==) — O professor relaxado. Aceita 4 e "4" como a mesma resposta porque o _significado_ é similar. Converte valores para combinar antes de comparar.
  • Igualdade estrita (===) — O professor rigoroso. Só aceita a resposta _exata_ no _formato exato_. O número 4 e a string "4" são respostas diferentes.
  • typeof — Pergunta "Que tipo de resposta é essa?" É um número? Uma string? Outra coisa?
  • Object.is() — O professor mais preciso. Ainda mais rigoroso que === — consegue detectar diferenças mínimas que os outros não veem.

TL;DR: Use === para quase tudo. Use == null para verificar se algo é null ou undefined. Use Object.is() apenas para casos extremos de NaN ou ±0.

03

seção

Igualdade Solta (`==`): A Comparação Relaxada

O operador == tenta ser prestativo. Antes de comparar dois valores, ele os converte para o mesmo tipo. Essa conversão automática é a coerção de tipo.

Por exemplo, se você compara o número 5 com a string "5", o JavaScript pensa: "Esses parecem similares. Deixa eu converter e verificar." Então 5 == "5" retorna true.

Como Funciona

Quando você escreve x == y, o JavaScript pergunta:

  1. x e y são do mesmo tipo? → Compara diretamente
  1. São tipos diferentes? → Converte um ou ambos para combinar, depois compara

Essa conversão automática pode ser útil, mas também pode causar resultados inesperados.

O Algoritmo de Igualdade Abstrata

Aqui está o algoritmo completo da especificação ECMAScript. Ao comparar x == y:

Mesmo Tipo?

Se x e y são do mesmo tipo, realiza comparação de igualdade estrita (===).

snippetJavaScript
5 == 5              // Mesmo tipo (number), compara diretamente → true"hello" == "hello"  // Mesmo tipo (string), compara diretamente → true

null e undefined

Se x é null e y é undefined (ou vice-versa), retorna true.

snippetJavaScript
null == undefined    // true (caso especial!)undefined == null    // true

Number e String

Se um é Number e o outro é String, converte a String para Number.

snippetJavaScript
5 == "5"    // "5" → 5, depois 5 == 5 → true0 == ""     // "" → 0, depois 0 == 0 → true42 == "42"  // "42" → 42, depois 42 == 42 → true

BigInt e String

Se um é BigInt e o outro é String, converte a String para BigInt.

snippetJavaScript
10n == "10"   // "10" → 10n, depois 10n == 10n → true

Conversão Booleana

Se qualquer valor é Boolean, converte para Number (true → 1, false → 0).

snippetJavaScript
true == 1     // true → 1, depois 1 == 1 → truefalse == 0    // false → 0, depois 0 == 0 → truetrue == "1"   // true → 1, depois 1 == "1" → 1 == 1 → true

Objeto para Primitivo

Se um é Object e o outro é String, Number, BigInt ou Symbol, converte o Object para primitivo usando ToPrimitive.

snippetJavaScript
[1] == 1       // [1] → "1" → 1, depois 1 == 1 → true[""] == 0      // [""] → "" → 0, depois 0 == 0 → true

BigInt e Number

Se um é BigInt e o other é Number, compara seus valores matemáticos.

snippetJavaScript
10n == 10      // Compara valores: 10 == 10 → true10n == 10.5    // 10 !== 10.5 → false

Sem Correspondência

Se nenhuma regra acima se aplica, retorna false.

snippetJavaScript
null == 0             // false (null só iguala undefined)undefined == 0        // falseSymbol() == Symbol()  // false (Symbols são sempre únicos)

Visual: A Árvore de Decisão da Coerção

snippettext
                              x == y                                 │                    ┌────────────┴────────────┐                    ▼                         ▼               Mesmo tipo?                Tipos diferentes?                    │                         │                   SIM                       SIM                    │                         │                    ▼                         ▼            Compara valores           ┌────────┴────────┐            (como ===)               │                 │                                     ▼                 ▼                              null == undefined?   Aplica regras                                     │              de coerção                                    SIM                 │                                     │                  ▼                                     ▼             Converte tipos                                   true            e compara                                                     novamente

Tabela Completa de Regras de Coerção

Tipo de xTipo de yCoerção Aplicada
NumberStringToNumber(y) — String vira Number
StringNumberToNumber(x) — String vira Number
BigIntStringToBigInt(y) — String vira BigInt
StringBigIntToBigInt(x) — String vira BigInt
BooleanQualquerToNumber(x) — Boolean vira Number (0 ou 1)
QualquerBooleanToNumber(y) — Boolean vira Number (0 ou 1)
ObjectString/Number/BigInt/SymbolToPrimitive(x) — Object vira primitivo
String/Number/BigInt/SymbolObjectToPrimitive(y) — Object vira primitivo
BigIntNumberCompara valores matemáticos diretamente
NumberBigIntCompara valores matemáticos diretamente
nullundefinedtrue (caso especial)
undefinednulltrue (caso especial)
nullQualquer (exceto undefined)false
undefinedQualquer (exceto null)false

Galeria de Resultados Surpreendentes

Aqui estão comparações que surpreendem a maioria dos desenvolvedores:

String & Number

snippetJavaScript
// String convertida para Number1 == "1"              // true  ("1" → 1)0 == ""               // true  ("" → 0)0 == "0"              // true  ("0" → 0)100 == "1e2"          // true  ("1e2" → 100) // Mas string com string é comparação direta"" == "0"             // false (ambas strings, valores diferentes) // Conversões NaNNaN == "NaN"          // false (NaN ≠ qualquer coisa, inclusive a si)0 == "hello"          // false ("hello" → NaN, 0 ≠ NaN)

Coerção Booleana

snippetJavaScript
// Booleans viram 0 ou 1 PRIMEIROtrue == 1             // true  (true → 1)false == 0            // true  (false → 0)true == "1"           // true  (true → 1, "1" → 1)false == ""           // true  (false → 0, "" → 0) // Por isso estes confundem:true == "true"        // false! (true → 1, "true" → NaN)false == "false"      // false! (false → 0, "false" → NaN) // E estes parecem errados:true == 2             // false (true → 1, 1 ≠ 2)true == "2"           // false (true → 1, "2" → 2, 1 ≠ 2)

Armadilha comum: true == "true" é false! O boolean true vira 1, e a string "true" vira NaN. Como 1 ≠ NaN, o resultado é false.

null & undefined

snippetJavaScript
// A relação especialnull == undefined     // true  (regra especial!)undefined == null     // true // Mas não igualam mais nadanull == 0             // falsenull == false         // falsenull == ""            // falseundefined == 0        // falseundefined == false    // falseundefined == ""       // false // Isso é útil de verdade!let value = null;if (value == null) {  // Pega AMBOS null E undefined  console.log("Valor é nullish");}

Este é o ÚNICO caso de uso legítimo para ==. Usar value == null verifica null e undefined numa única comparação.

Arrays & Objetos

snippetJavaScript
// Arrays convertem via ToPrimitive (geralmente toString)[] == false           // true  ([] → "" → 0, false → 0)[] == 0               // true  ([] → "" → 0)[] == ""              // true  ([] → "")[1] == 1              // true  ([1] → "1" → 1)[1] == "1"            // true  ([1] → "1")[1,2] == "1,2"        // true  ([1,2] → "1,2") // Gotcha do array vazio[] == ![]             // true! (veja explicação abaixo) // Objetos com valueOf/toStringlet obj = { valueOf: () => 42 };obj == 42             // true  (obj.valueOf() → 42)

Passo a Passo: [] == ![]

Este é um dos resultados mais surpreendentes do JavaScript. Um array vazio [] iguala ![]? Vamos decompor:

Avaliar ![]

Primeiro, o JavaScript avalia ![].

  • [] é truthy (todos os objetos são truthy)
  • ![] portanto é false
  • Agora temos: [] == false

Boolean para Number

Um lado é Boolean, então converte para Number.

  • false → 0
  • Agora temos: [] == 0

Objeto para Primitivo

Um lado é Object, converte para primitivo.

  • [] → "" (array vazio vira string vazia)
  • Agora temos: "" == 0

String para Number

Um lado é String, converte para Number.

  • "" → 0
  • Agora temos: 0 == 0

Comparação Final

snippetJavaScript
0 == 0    // true!

Por isso [] == ![] retorna true. Com ===, seria false imediatamente (tipos diferentes).

O Único Caso Aceitável para ==

snippetJavaScript
function greet(name) {  if (name == null) {    return "Olá, estranho!";  }  return `Olá, ${name}!`;} greet(null);       // "Olá, estranho!"greet(undefined);  // "Olá, estranho!"greet("Alice");    // "Olá, Alice!"greet("");         // "Olá, !"  (string vazia NÃO é null)greet(0);          // "Olá, 0!" (0 NÃO é null)

Muitos guias de estilo (incluindo Airbnb e StandardJS) fazem exceção para value == null porque é uma forma limpa de verificar valores "nullish". Você também pode usar o operador nullish coalescing (??) ou optional chaining (?.) do ES2020.

04

seção

Igualdade Estrita (`===`): A Escolha Confiável

O operador de igualdade estrita compara dois valores sem nenhuma conversão. Se os tipos são diferentes, retorna false imediatamente.

Este é o operador que você deve usar quase sempre. É simples e previsível: o número 1 e a string "1" são tipos diferentes, então 1 === "1" retorna false. Sem surpresas.

Como Funciona

Quando você escreve x === y, o JavaScript pergunta:

  1. x e y são do mesmo tipo? Não → retorna false
  1. Mesmo tipo? → Compara os valores

É isso. Sem conversões, sem surpresas (bem, quase — há um caso especial com NaN).

O Algoritmo de Igualdade Estrita

Verificação de Tipo

Se x e y são tipos diferentes, retorna false imediatamente.

snippetJavaScript
1 === "1"          // false (number vs string)true === 1         // false (boolean vs number)null === undefined // false (null vs undefined)

Comparação de Number

Se ambos são Numbers:

  • Se qualquer um é NaN, retorna false
  • Se ambos têm o mesmo valor numérico, retorna true
  • +0 e -0 são considerados iguais
snippetJavaScript
42 === 42              // trueNaN === NaN            // false (!)+0 === -0              // trueInfinity === Infinity  // true

Comparação de String

Se ambos são Strings, retorna true se têm os mesmos caracteres na mesma ordem.

snippetJavaScript
"hello" === "hello"   // true"hello" === "Hello"   // false (case sensitive)"hello" === "hello "  // false (comprimentos diferentes)

Comparação de Boolean

snippetJavaScript
true === true     // truefalse === false   // truetrue === false    // false

Comparação de BigInt

snippetJavaScript
10n === 10n       // true10n === 20n       // false

Comparação de Symbol

snippetJavaScript
const sym = Symbol("id");sym === sym                    // trueSymbol("id") === Symbol("id")  // false (symbols diferentes!)

Comparação de Object (Referência)

Se ambos são Objects (incluindo Arrays e Functions), retorna true apenas se são o mesmo objeto (mesma referência na memória).

snippetJavaScript
const obj = { a: 1 };obj === obj       // true (mesma referência){ a: 1 } === { a: 1 }  // false (objetos diferentes!)[] === []         // false (arrays diferentes!)

null e undefined

snippetJavaScript
null === null           // trueundefined === undefined // truenull === undefined      // false

Visual: Fluxograma da Igualdade Estrita

snippettext
                           x === y                              │              ┌───────────────┴───────────────┐              │          Mesmo tipo?           │              └───────────────┬───────────────┘                     │                 │                    NÃO               SIM                     │                 │                     ▼                 ▼                  false          Ambos NaN?                                      │                              ┌───────┴───────┐                             SIM             NÃO                              │               │                              ▼               ▼                           false        Mesmo valor?                     (NaN nunca iguala         │                        nada!)         ┌───────┴───────┐                                      SIM             NÃO                                       │               │                                       ▼               ▼                                     true           false

Resultados Previsíveis

snippetJavaScript
// Todos false (tipos diferentes)1 === "1"              // false0 === ""               // falsetrue === 1             // falsefalse === 0            // falsenull === undefined     // false[] === ""              // false // Todos true (mesmo tipo, mesmo valor)1 === 1                // true"hello" === "hello"    // truetrue === true          // truenull === null          // trueundefined === undefined // true

Casos Especiais: Duas Exceções

NaN !== NaN

snippetJavaScript
NaN === NaN           // false! // NaN não iguala nada, nem a si mesmo!// Isso é por design (spec IEEE 754) // Como verificar NaN:Number.isNaN(NaN)     // true (recomendado)isNaN(NaN)            // true (mas tem quirks)Object.is(NaN, NaN)   // true (ES6) // O quirk do isNaN():isNaN("hello")        // true! (converte primeiro)Number.isNaN("hello") // false (correto)

Use Number.isNaN() em vez do isNaN() global para verificação confiável de NaN.

+0 === -0

snippetJavaScript
+0 === -0             // true-0 === 0              // true // Mas SÃO diferentes! Observe:1 / +0                // Infinity1 / -0                // -Infinity // Como distinguir:Object.is(+0, -0)     // false (ES6)1 / +0 === 1 / -0     // false (Infinity vs -Infinity)

Comparação de Objetos: Referência vs Valor

snippetJavaScript
const obj1 = { name: "Alice" };const obj2 = { name: "Alice" };const obj3 = obj1; obj1 === obj2    // false (objetos diferentes na memória)obj1 === obj3    // true  (mesma referência) const arr1 = [1, 2, 3];const arr2 = [1, 2, 3];const arr3 = arr1; arr1 === arr2    // false (arrays diferentes)arr1 === arr3    // true  (mesma referência)
snippettext
VISUALIZAÇÃO NA MEMÓRIA:obj1 ──────┐           ├──► { name: "Alice" }    (Objeto A)obj3 ──────┘obj2 ──────────► { name: "Alice" }   (Objeto B)obj1 === obj3 → true  (ambos apontam para Objeto A)obj1 === obj2 → false (objetos diferentes, mesmo conteúdo)

Para comparar objetos pelo conteúdo (igualdade profunda), use JSON.stringify() para objetos simples, escreva uma função recursiva, ou use uma biblioteca como _.isEqual() do Lodash.

05

seção

`Object.is()`: Igualdade Same-Value

O ES6 introduziu Object.is() para corrigir os dois casos extremos onde === dá resultados inesperados. Conforme documentado pela MDN, Object.is() implementa o algoritmo "SameValue" da especificação ECMAScript. Funciona exatamente como ===, mas trata NaN e -0 corretamente.

Por Que Existe

snippetJavaScript
// Os dois casos onde === está "errado"NaN === NaN       // false (mas NaN É NaN!)+0 === -0         // true  (mas SÃO diferentes!) // Object.is() corrige ambosObject.is(NaN, NaN)   // true ✓Object.is(+0, -0)     // false ✓

Como Difere de ===

Object.is() se comporta exatamente como ===, exceto nestes dois casos:

Expressão===Object.is()
NaN, NaNfalsetrue
+0, -0truefalse
-0, 0truefalse
1, 1truetrue
"a", "a"truetrue
null, nulltruetrue
{}, {}falsefalse

Tabela de Comparação Completa

Valores=====Object.is()
1, "1"truefalsefalse
0, falsetruefalsefalse
null, undefinedtruefalsefalse
NaN, NaNfalsefalsetrue
+0, -0truetruefalse
[], []falsefalsefalse
{}, {}falsefalsefalse

Quando Usar Object.is()

snippetJavaScript
// 1. Verificar NaN (alternativa a Number.isNaN)function isReallyNaN(value) {  return Object.is(value, NaN);} // 2. Distinguir +0 de -0 (raro, mas necessário em math/física)function isNegativeZero(value) {  return Object.is(value, -0);} // 3. Implementar comparação SameValue (como em Map/Set)const map = new Map();map.set(NaN, "valor");map.get(NaN);  // "valor" (NaN funciona como chave!)

Para a maioria do código do dia a dia, você não precisará de Object.is(). Use === como padrão e recorra a Object.is() apenas quando precisar tratar casos extremos de NaN ou ±0.

06

seção

O Operador `typeof`

O operador typeof informa qual é o tipo de um valor. Retorna uma string como "number", "string" ou "boolean". A pesquisa State of JS 2023 encontrou que a adoção de TypeScript continua crescendo — em parte porque desenvolvedores buscam evitar as armadilhas de verificação de tipo que o typeof sozinho não resolve. É muito útil, mas tem quirks famosos que surpreendem muitos desenvolvedores.

Como Funciona

snippetJavaScript
typeof operandtypeof(operand)  // Ambas as formas são válidas

Tabela Completa de Resultados

ValorResultado typeofNotas
"hello""string"
42"number"Inclui Infinity, NaN
42n"bigint"ES2020
true / false"boolean"
undefined"undefined"
Symbol()"symbol"ES6
null"object"Bug famoso!
{}"object"
[]"object"Arrays são objetos
function(){}"function"Caso especial
class {}"function"Classes são funções
new Date()"object"
/regex/"object"

Os Quirks Famosos

typeof null === 'object' — Um Bug Famoso

snippetJavaScript
typeof null    // "object" — Espera, o quê?!

Por quê? Este é um bug da primeira versão do JavaScript em 1995. No código original, valores eram armazenados com uma tag de tipo. Objetos tinham a tag 000, e null era representado como 0x00, que também correspondia à tag de objeto.

Por que não foi corrigido? Código existente demais depende desse comportamento. Mudar agora quebraria milhões de sites.

snippetJavaScript
// Sempre verifique null explicitamentefunction getType(value) {  if (value === null) return "null";  return typeof value;} if (value !== null && typeof value === "object") {  // É definitivamente um objeto (não null)}

Arrays Retornam 'object'

snippetJavaScript
typeof []           // "object"typeof [1, 2, 3]    // "object"

Por quê? Arrays SÃO objetos no JavaScript. Use Array.isArray() para verificar arrays.

snippetJavaScript
Array.isArray([])           // true (recomendado)Array.isArray({})           // falseObject.prototype.toString.call([])  // "[object Array]"

Functions Retornam 'function'

snippetJavaScript
typeof function() {}    // "function"typeof (() => {})       // "function"typeof class {}         // "function"

Funções são tecnicamente objetos, mas typeof as trata especialmente porque verificar valores "callable" é tão comum.

typeof em Variáveis Não Declaradas

snippetJavaScript
console.log(undeclaredVar);  // ReferenceError!typeof undeclaredVar         // "undefined" (sem erro!)

Isso permite detecção segura de features:

snippetJavaScript
if (typeof jQuery !== "undefined") {  // jQuery está disponível}

NaN é 'number' — Sim, De Verdade

snippetJavaScript
typeof NaN          // "number"

"Not a Number" tem typeof "number". NaN é um valor especial no sistema numérico que representa um cálculo sem resultado válido.

snippetJavaScript
Number.isNaN(NaN)  // true

Alternativas Melhores para Verificação de Tipo

snippetJavaScript
Array.isArray(value)           // true só para arraysNumber.isNaN(value)            // true só para NaN (sem coerção)Number.isFinite(value)         // true para números finitosNumber.isInteger(value)        // true para inteirosNumber.isSafeInteger(value)    // true para inteiros seguros

Object.prototype.toString

snippetJavaScript
const getType = (value) =>  Object.prototype.toString.call(value).slice(8, -1); getType(null)           // "Null"getType([])             // "Array"getType({})             // "Object"getType(new Date())     // "Date"getType(/regex/)        // "RegExp"getType(42)             // "Number"getType("hello")        // "String"

Verificador de Tipo Customizado

snippetJavaScript
function getType(value) {  if (value === null) return "null";  const type = typeof value;  if (type !== "object" && type !== "function") return type;  const tag = Object.prototype.toString.call(value);  return tag.slice(8, -1).toLowerCase();} getType(null)    // "null"getType([])      // "array"getType({})      // "object"
07

seção

Guia de Decisão: Qual Usar?

A Regra Simples

Use === como padrão para todas as comparações. É previsível, não faz coerção de tipo, e vai te poupar incontáveis bugs.

A única exceção: use == null para verificar null e undefined numa única comparação.

Fluxograma de Decisão

snippettext
                    Precisa comparar dois valores?                              │                              ▼              ┌───────────────────────────────┐              │ Verificando null/undefined?     │              └───────────────────────────────┘                      │               │                     SIM             NÃO                      │               │                      ▼               ▼               ┌──────────┐   ┌───────────────────┐               │ == null  │   │ Precisa NaN ou ±0?│               └──────────┘   └───────────────────┘                                  │           │                                 SIM          NÃO                                  │           │                                  ▼           ▼                            ┌──────────┐ ┌─────────┐                            │Object.is │ │   ===   │                            │    ou    │ └─────────┘                            │Number.   │                            │ isNaN()  │                            └──────────┘

Referência Rápida

CenárioUseExemplo
Comparação padrão===if (x === 5)
Verificar nullish== nullif (value == null)
Verificar NaNNumber.isNaN()if (Number.isNaN(x))
Verificar arrayArray.isArray()if (Array.isArray(x))
Verificar tipotypeofif (typeof x === "string")
Distinguir ±0Object.is()Object.is(x, -0)

Configuração ESLint

A maioria dos guias de estilo exige === com exceção para verificações de null:

snippetJavaScript
// .eslintrc.jsmodule.exports = {  rules: {    // Exige === e !== exceto para comparações com null    "eqeqeq": ["error", "always", { "null": "ignore" }]  }};

Isso permite:

snippetJavaScript
// Permitidoif (value === 5) { }      // Usando ===if (value == null) { }    // Exceção para null // Erroif (value == 5) { }       // Deveria usar ===

Configure a regra eqeqeq no ESLint do seu projeto para reforçar === automaticamente — com a opção "null": "ignore" que permite o padrão value == null.

08

seção

Gotchas e Erros Comuns

Estes erros comuns pegam muitos desenvolvedores JavaScript. Aprender sobre eles agora vai economizar tempo de debugging depois:

1. Comparar Objetos por Valor

snippetJavaScript
const user1 = { name: "Alice" };const user2 = { name: "Alice" }; if (user1 === user2) {  console.log("Mesmo usuário!");  // Nunca executa!}

Por que está errado: objetos são comparados por referência, não por valor.

snippetJavaScript
if (user1.name === user2.name) { }  // Compara propriedadesif (JSON.stringify(user1) === JSON.stringify(user2)) { }  // Objetos simplesimport { isEqual } from 'lodash';if (isEqual(user1, user2)) { }  // Biblioteca

2. Confusão Truthy/Falsy com ==

snippetJavaScript
if ([] == false) { }      // true! (mas [] é truthy)if ("0" == false) { }     // true! (mas "0" é truthy)if (" " == false) { }     // false (mas " " é truthy)

O operador == não verifica truthiness — faz coerção de tipo.

snippetJavaScript
if (value === false) { }  // Só true para false realif (!value) { }           // Verificação falsyif (value) { }            // Verificação truthy

3. Comparações com NaN

snippetJavaScript
const result = parseInt("hello");if (result === NaN) { }  // Nunca executa!
snippetJavaScript
if (Number.isNaN(result)) { }  // Funciona!if (Object.is(result, NaN)) { }  // Também funciona!

4. A Armadilha do typeof null

snippetJavaScript
function processObject(obj) {  if (typeof obj === "object") {    console.log(obj.property);  // TypeError se null!  }}processObject(null);  // Quebra!
snippetJavaScript
if (obj !== null && typeof obj === "object") { }console.log(obj?.property);  // Optional chaining (ES2020)

5. Gotchas de Comparação de String

snippetJavaScript
console.log("10" > "9");    // false! (comparação lexicográfica)
snippetJavaScript
console.log(Number("10") > Number("9"));  // trueconsole.log(+"10" > +"9");                // true["10", "9", "2"].sort((a, b) => a - b);  // ["2", "9", "10"]

6. Comparações com Array Vazio

snippetJavaScript
const arr = [];console.log(arr == false);        // trueconsole.log(arr ? "sim" : "não"); // "sim"// arr iguala false mas é truthy?!
snippetJavaScript
if (arr.length === 0) { console.log("Array vazio"); }if (!arr.length) { console.log("Array vazio"); }
09

seção

Equívocos Comuns

Equívoco 1: '== é sempre ruim e nunca deve ser usado'

Nem sempre! Embora === deva ser seu padrão, há um caso legítimo para ==:

snippetJavaScript
if (value == null) {  // Pega AMBOS null E undefined} if (value === null || value === undefined) {  // Mesmo resultado, mas mais verboso}

Isso é mais limpo e é explicitamente permitido pela maioria dos guias de estilo (incluindo a regra eqeqeq do ESLint com a opção "null": "ignore").

Equívoco 2: '=== verifica se os tipos são iguais'

Parcialmente errado! === verifica se dois valores têm o mesmo tipo E o mesmo valor.

snippetJavaScript
5 === 10          // false (ambos numbers, valores diferentes)"hello" === "hi"  // false (ambas strings, valores diferentes)5 === "5"         // false (tipos diferentes — comparação de valor nem tentada)

Equívoco 3: 'typeof é confiável para verificar todos os tipos'

snippetJavaScript
typeof null         // "object" — bug famoso de 1995!typeof []           // "object" — arrays são objetostypeof NaN          // "number"typeof function(){} // "function" — mas funções SÃO objetos!

Melhor: Array.isArray(), value === null, Number.isNaN(), Object.prototype.toString.call().

Equívoco 4: 'Objetos com o mesmo conteúdo são iguais'

snippetJavaScript
{ a: 1 } === { a: 1 }  // false — objetos diferentes na memória![] === []              // false(() => {}) === (() => {})  // false const obj = { a: 1 };obj === obj            // true — mesma referência

Equívoco 5: 'NaN significa que o valor não é um número'

snippetJavaScript
typeof NaN  // "number" — NaN É um tipo number! 0 / 0           // NaNMath.sqrt(-1)   // NaNparseInt("xyz") // NaN

Pense em NaN como "o resultado de um cálculo que não produz um número significativo".

Equívoco 6: 'Valores truthy são == true'

snippetJavaScript
"hello" == true   // false!2 == true         // false![] == true        // false! if ("hello") { }  // executaif (2) { }        // executaif ([]) { }       // executa

Regra: não use == true ou == false. Use === ou confie na truthiness: if (value).

10

seção

Teste Seu Conhecimento

$ summary --quick

Resumo rápido

  • Use === por padrão — É previsível e não converte tipos
  • == converte tipos primeiro — Isso leva a resultados inesperados como "0" == false ser true
  • Use == só para null checks — value == null verifica null e undefined juntos
  • NaN !== NaN — NaN não iguala nada, nem a si mesmo. Use Number.isNaN() para verificar
  • Objetos comparam por referência — {} === {} é false porque são objetos diferentes na memória
  • typeof null === "object" — Bug que não pode ser corrigido. Sempre verifique null diretamente
  • Object.is() para casos extremos — Use quando precisar verificar NaN ou distinguir +0 de -0
  • Arrays retornam "object" do typeof — Use Array.isArray() para verificar arrays
  • Regras comuns em entrevistas — Agora você está preparado!
  • Configure ESLint — Use a regra eqeqeq para reforçar === nos seus projetos

Créditos da série

Este artigo faz parte de uma série de estudos inspirada no projeto 33 Conceitos JS, criado por Leonardo Maldonado. Todo o conteúdo original está disponível em 33jsconcepts.com.