Operadores em JavaScript: como as expressões realmente funcionam
Toda linha não-trivial de JavaScript é montada a partir de operadores — símbolos que recebem um ou dois valores e produzem um novo. O + soma, o === compara, o && combina booleanos, o ? : escolhe entre dois valores. A maioria é familiar para quem vem de outras linguagens; mas alguns têm particularidades do JavaScript que vale conhecer logo de cara.
Vamos passar por eles agrupados por categoria, deixando para o final aqueles que você quase não usa, mas que fazem diferença quando precisa.
Operadores aritméticos em JavaScript
Os operadores aritméticos básicos se comportam como você espera:
Alguns detalhes que vale a pena destacar:
/sempre faz divisão de ponto flutuante.7 / 2dá3.5, e não3. Se você quer um inteiro, useMath.floor(7 / 2)ouMath.trunc(7 / 2).%é o resto da divisão, não o módulo matemático de verdade. Ele mantém o sinal do operando da esquerda:-7 % 3resulta em-1, não2.- O
+é sobrecarregado. Se qualquer um dos lados for uma string, ele concatena em vez de somar:"3" + 1vira"31". Já já falamos mais sobre isso.
Incremento e decremento
A diferença entre count++ e ++count só importa quando você usa o valor da expressão na mesma linha. Se for uma instrução isolada, fazem a mesma coisa. A maioria dos guias de estilo prefere count += 1 por ser mais claro.
O operador + tem dupla personalidade
Essa aqui já pegou todo mundo pelo menos uma vez:
Se pelo menos um dos operandos for uma string, o + vira concatenação de strings e converte o outro lado também para string. Já os demais operadores aritméticos fazem o caminho contrário: convertem strings em números:
Resumindo: para montar strings, prefira template literals (`price: ${5}`). Para fazer contas, garanta que seus valores são realmente números — Number(x) ou parseInt(x, 10) faz a conversão explícita.
Operadores de comparação em JavaScript
Comparações retornam booleanos. Existem duas variações: estrita e não estrita.
=== e !== fazem comparação estrita — mesmo valor e mesmo tipo. Já == e != convertem os tipos antes de comparar, o que gera aquelas surpresas clássicas: null == undefined dá true e [] == false também dá true. Por padrão, use sempre === e !==. A única exceção comum é x == null, um atalho prático para verificar se x é null ou undefined.
Os operadores de ordenação funcionam como você espera com números e, no caso de strings, comparam em ordem alfabética:
A comparação de strings usa os códigos dos caracteres, ou seja, diferencia maiúsculas de minúsculas. Se você precisa de uma ordenação mais "humana", vá de String.prototype.localeCompare.
Operadores lógicos em JavaScript
&& (E), || (OU) e ! (NÃO) combinam valores booleanos — mas, na prática, eles vão bem além da álgebra booleana tradicional.
O detalhe curioso: && e || não retornam true ou false. Eles devolvem um dos seus operandos. O && retorna o primeiro valor falsy, ou o último caso todos sejam truthy. Já o || retorna o primeiro valor truthy, ou o último se todos forem falsy.
É por isso que você vai ver bastante esse tipo de padrão: const displayName = user.name || "Guest" — ou seja, pega o primeiro valor que não for "vazio". É enxuto, mas fica o alerta: o || trata 0, "" e false como se fossem valores a serem descartados, caindo no fallback. Se algum desses for um valor válido no seu caso, use ?? (que vem logo abaixo).
Os dois operadores também fazem short-circuit (avaliação em curto-circuito): se o lado esquerdo já define a resposta, o lado direito nem chega a ser executado.
O operador de coalescência nula ??
O ?? funciona parecido com o ||, mas só entra em ação quando o valor é null ou undefined — ele ignora 0, "" e false.
Use ?? quando um valor legítimo pode ser falsy — contadores, strings vazias, false explícito. Use || quando qualquer valor falsy deve ser tratado como "ausente". Em código moderno, ?? é o padrão mais seguro para valores opcionais com defaults não nulos.
Operadores de atribuição
O = atribui um valor. Já as formas compostas combinam atribuição com outro operador:
Também existem os operadores de atribuição lógica — ||=, &&= e ??= — que só fazem a atribuição quando o valor atual atende a uma condição:
Úteis para definir valores padrão sem precisar escrever um if gigante.
O operador ternário em JavaScript
O condição ? a : b é a versão em expressão do if/else. Ele devolve a quando a condição é verdadeira (truthy) e b caso contrário:
O operador ternário brilha quando a ideia é escolher um valor de forma enxuta. Só que, no instante em que você começa a aninhar ternários, a legibilidade vai embora — se você se pegar escrevendo a ? b : c ? d : e, é hora de partir pra um if/else ou um objeto de lookup.
typeof e instanceof
O typeof devolve uma string descrevendo o tipo do operando:
Duas pegadinhas que vale a pena memorizar: typeof null devolve "object" (um bug de 1995 que virou permanente), e arrays também aparecem como "object". Para arrays, use Array.isArray(x); para null, use x === null.
Já o instanceof verifica se um objeto foi criado a partir de um determinado construtor:
Spread e rest usam o mesmo ...
Você vai encontrar o ... em dois contextos diferentes. Como spread, ele expande um iterável em elementos individuais:
Como rest, ele agrupa vários valores em um único array — normalmente em parâmetros de função ou em desestruturação:
Mesma sintaxe, funções opostas. Spread desempacota; rest agrupa. O que decide qual é qual é o contexto: numa chamada ou literal, ele espalha; numa lista de parâmetros ou padrão de desestruturação, ele coleta.
Precedência de operadores em JavaScript (na dúvida, use parênteses)
Os operadores têm uma precedência que define qual deles roda primeiro quando você mistura vários. Multiplicação vem antes da soma, comparação vem antes dos lógicos, e por aí vai:
A tabela completa é enorme e ninguém decora tudo. Um hábito simples resolve 99% dos casos: sempre que você misturar operadores e não tiver certeza da ordem, use parênteses. O código fica mais legível e não depende da memória de quem está lendo.
Operadores bitwise (raramente é o que você quer)
Só pra não deixar de fora: &, |, ^, ~, <<, >> e >>> trabalham sobre a representação binária de inteiros. Você vai encontrar esses operadores em código de gráficos, protocolos de baixo nível e em uma ou outra API que usa bitmask pra flags.
Um truque clássico (mas questionável): n | 0 trunca um número para um inteiro de 32 bits, e muita gente já abusou disso como se fosse um Math.trunc mais rápido. Não faça isso — Math.trunc é mais claro e funciona para números fora da faixa de 32 bits.
A seguir: if/else
Operadores produzem valores; o if/else usa esses valores para decidir qual bloco de código executar. Boa parte do que você vai fazer com os operadores de comparação e lógicos vistos acima é justamente jogar o resultado deles dentro de condicionais — que é exatamente o assunto da próxima página.
Perguntas frequentes
Quais são os principais operadores em JavaScript?
O JavaScript tem operadores aritméticos (+, -, *, /, %, **), de comparação (===, !==, <, >), lógicos (&&, ||, !), de atribuição (=, +=, -=) e alguns especiais como o ternário ? :, o typeof e o nullish coalescing ??. São os blocos de construção para montar expressões e controlar o fluxo do código.
Qual a diferença entre == e === no JavaScript?
O === compara valor e tipo ao mesmo tempo. Já o == faz coerção de tipos antes de comparar, então 0 == "0" dá true, mas 0 === "0" dá false. Use === por padrão — as regras de coerção do == são sutis o bastante para gerar bugs que passam batido no code review.
Para que serve o operador ternário no JavaScript?
O condição ? a : b é basicamente um if/else de uma linha que devolve um valor. Se condição for truthy, retorna a; caso contrário, b. Funciona bem em expressões condicionais curtas como const label = count === 1 ? 'item' : 'items', mas aninhar vários ternários vira um pesadelo de ler.
Quando usar ?? em vez de ||?
O || cai no valor padrão para qualquer valor falsy, incluindo 0, "" e false. Já o ?? só entra em ação com null ou undefined. Se você quer que count ?? 10 mantenha um 0 legítimo, use ??. Se realmente quer que qualquer falsy dispare o fallback, fica com o || mesmo.