if else em JavaScript: como escrever condições
O if não testa true, testa truthiness. Ordem do else if, o if sem chaves que engana, early return e o SyntaxError Unexpected token else, tudo executado.
if é como o programa toma decisão: ele avalia uma expressão, e se o resultado
for verdadeiro executa o bloco entre chaves. O else é o caminho de quem não
passou no teste.
A parte que ninguém avisa é que o if não testa true — ele testa
truthiness. Qualquer valor entra ali dentro, e o motor converte para booleano
antes de decidir. É por isso que if (carrinho.itens) continua entrando mesmo
com o carrinho vazio, e o bug fica invisível por semanas.
Os exemplos são todos de uma loja: frete, pedido, estoque. O mesmo domínio de variáveis em JavaScript.
O termo técnico para essa escolha é fluxo condicional. Em palavras simples, o programa faz uma pergunta, converte o resultado para booleano e executa apenas o caminho correspondente. A qualidade da pergunta decide a qualidade da decisão.
A catraca faz uma pergunta por vez
Uma catraca de evento pode perguntar “o ingresso é válido?” e liberar ou barrar
a passagem. Se a regra pergunta apenas “existe um cartão?”, um cartão vazio
ainda pode passar. O if age sobre a condição escrita, não sobre a intenção de
quem programou. Com truthiness, o JavaScript também converte valores que não são
true ou false antes de escolher o bloco.
Antes do primeiro exemplo, escreva a conversão booleana de cada valor usado na
condição e escolha o ramo esperado. Depois confira a saída. Quando errar, teste
o valor isolado com Boolean(...): isso revela a conversão responsável sem
culpar o if inteiro.
const total = 250;
if (total >= 199) {
console.log('Frete grátis');
} else {
console.log('Frete: R$ 24,90');
}Entre os parênteses vai uma expressão — algo que produz um valor. total >= 199
produz true. O bloco do if roda; o do else é ignorado. Só um dos dois roda,
sempre.
O if não testa true — testa truthiness
Aqui está o comportamento que decide metade dos bugs de condição em JavaScript:
const cupom = '';
const observacao = ' ';
const itens = [];
const desconto = 0;
if (cupom) console.log('cupom aplicado');
if (observacao) console.log('tem observação');
if (itens) console.log('tem itens');
if (desconto) console.log('tem desconto');
console.log('fim');Leia a saída com calma. cupom vazio não entrou, mas observacao com três
espaços entrou — espaço é caractere. E o pior: itens entrou com o array
vazio. Um array vazio é um objeto, e todo objeto é truthy.
A lista de valores falsy é fechada e tem oito itens: false, 0, -0, 0n,
'', null, undefined e NaN. Tudo o mais é truthy — incluindo [], {},
a string '0' e a string 'false'. Cada conversão está executada em
truthy e falsy em JavaScript.
| valor | if (valor) entra? |
o que você provavelmente queria |
|---|---|---|
'' |
não | valor.trim() !== '' |
' ' |
sim | valor.trim() !== '' |
0 |
não | valor > 0 ou valor !== undefined |
[] |
sim | valor.length > 0 |
{} |
sim | Object.keys(valor).length > 0 |
null / undefined |
não | valor != null |
NaN |
não | Number.isFinite(valor) |
A correção é sempre a mesma: teste a pergunta de verdade, não a existência do valor.
const pedido = { cliente: 'Ana', itens: [], desconto: 0 };
console.log(Boolean(pedido.itens));
console.log(pedido.itens.length > 0);
console.log(Boolean(pedido.desconto));
console.log(pedido.desconto > 0);Boolean(pedido.itens) dá true porque existe um array. pedido.itens.length > 0
dá false porque não existe item nenhum. As duas perguntas são diferentes, e
só a segunda é sobre o carrinho.
else if: a ordem das perguntas é o algoritmo
Encadear condições parece inofensivo até você errar a ordem. A loja cobra frete por faixa de valor:
function faixaDeFrete(total) {
if (total >= 49) {
return 'R$ 14,90';
} else if (total >= 99) {
return 'R$ 9,90';
} else if (total >= 199) {
return 'grátis';
}
return 'R$ 24,90';
}
console.log(faixaDeFrete(250));
console.log(faixaDeFrete(120));
console.log(faixaDeFrete(60));
console.log(faixaDeFrete(30));Pedido de R$ 250 pagando frete. A cadeia para na primeira condição
verdadeira, e 250 >= 49 já é verdade — as outras duas nunca são consultadas.
Nada quebra, nenhum erro aparece; a loja só cobra errado.
A ordem certa vai da faixa mais restritiva para a mais ampla:
function faixaDeFrete(total) {
if (total >= 199) {
return 'grátis';
} else if (total >= 99) {
return 'R$ 9,90';
} else if (total >= 49) {
return 'R$ 14,90';
}
return 'R$ 24,90';
}
console.log(faixaDeFrete(250));
console.log(faixaDeFrete(120));
console.log(faixaDeFrete(60));
console.log(faixaDeFrete(30));Regra prática para faixas numéricas: do maior para o menor, ou do menor para
o maior — mas nunca embaralhado. Se a cadeia tem mais de três else if, o
switch case e a tabela de faixas costumam ler
melhor que a escada.
O if sem chaves só leva a próxima instrução
A linguagem permite escrever if sem chaves. O bloco vira uma única instrução —
e é aqui que a indentação mente para você:
const itens = [{ nome: 'Mouse sem fio', preco: 89.9 }];
const total = itens.reduce((soma, item) => soma + item.preco, 0);
let frete = 24.9;
let etiqueta = 'frete padrão';
if (total >= 199)
frete = 0;
etiqueta = 'frete grátis';
console.log({ total, frete, etiqueta });O total é R$ 89,90. O frete continuou R$ 24,90 — correto. E a etiqueta na tela
diz “frete grátis”. A linha etiqueta = ... está indentada como se pertencesse
ao if, mas não pertence: ela roda sempre.
Esse bug tem uma característica cruel — ele nasce numa segunda edição. Alguém
escreveu o if de uma linha só, funcionando; meses depois outra pessoa
acrescentou a segunda linha embaixo, alinhada, e o Prettier manteve o alinhamento
sem reclamar. Escreva chaves sempre.
Early return: o padrão que apaga a escada de else
Validar entrada com if aninhado produz aquele código que vai andando para a
direita:
function resumirPedido(pedido) {
if (pedido) {
if (Array.isArray(pedido.itens) && pedido.itens.length > 0) {
if (pedido.cliente) {
const total = pedido.itens.reduce((soma, item) => soma + item.preco, 0);
return `${pedido.cliente}: R$ ${total.toFixed(2)}`;
} else {
return 'pedido sem cliente';
}
} else {
return 'carrinho vazio';
}
} else {
return 'pedido inexistente';
}
}
console.log(resumirPedido({ cliente: 'Ana', itens: [{ preco: 289.9 }] }));
console.log(resumirPedido({ cliente: 'Bruno', itens: [] }));
console.log(resumirPedido(null));Funciona. Mas o caminho feliz — a linha que realmente calcula o total — está
enterrado no terceiro nível, e o else que lhe corresponde está vinte linhas
abaixo. Agora a mesma função com early return: cada caso ruim sai na porta,
e o que sobra é o caso bom.
function resumirPedido(pedido) {
if (!pedido) return 'pedido inexistente';
if (!Array.isArray(pedido.itens) || pedido.itens.length === 0) return 'carrinho vazio';
if (!pedido.cliente) return 'pedido sem cliente';
const total = pedido.itens.reduce((soma, item) => soma + item.preco, 0);
return `${pedido.cliente}: R$ ${total.toFixed(2)}`;
}
console.log(resumirPedido({ cliente: 'Ana', itens: [{ preco: 289.9 }] }));
console.log(resumirPedido({ cliente: 'Bruno', itens: [] }));
console.log(resumirPedido(null));Mesma saída, zero else, zero aninhamento. As três primeiras linhas são as
cláusulas de guarda: leem como uma lista de pré-condições, e quem chega na
quarta linha sabe que pedido, pedido.itens e pedido.cliente existem.
Esse padrão também é a defesa mais barata contra o
TypeError: Cannot read properties of undefined:
a guarda barra o undefined antes que alguém tente ler .length dele.
== dentro do if é uma armadilha a mais
O if já converte o valor da condição. Se você usar == dentro dele, ganha uma
segunda conversão, agora entre os dois lados da comparação:
const quantidade = '0';
if (quantidade == 0) console.log('== considerou igual a zero');
if (quantidade === 0) console.log('=== considerou igual a zero');
console.log([] == false, '' == 0, null == undefined, null == false);A string '0' — que é truthy — comparou igual ao número 0 com ==. E
[] == false dá true, embora if ([]) entre. Um array vazio é
simultaneamente truthy e “igual a false”: as duas regras de conversão são
diferentes, e tentar guardar as duas na cabeça é perda de tempo.
Erros comuns: SyntaxError: Unexpected token 'else'
Este é o erro que mais aparece na primeira semana. Um ponto e vírgula depois da
chave de fechamento encerra o if — e aí o else fica órfão:
const total = 250;
if (total >= 199) {
console.log('Frete grátis');
};
else {
console.log('Frete: R$ 24,90');
}SyntaxError: Unexpected token ‘else’ at compileSourceTextModule (node:internal/modules/esm/utils:318:16) at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:90:18) at #translate (node:internal/modules/esm/loader:435:20)
Node.js v24.16.0
Repare em duas coisas. Primeiro: nenhuma linha rodou. SyntaxError acontece
na compilação do módulo, antes da primeira instrução — o console.log da linha 4
nunca existiu. Segundo: o Node aponta a linha 6, a do else, mas o defeito está
na linha 5. O motor só percebe o problema quando chega no token que não cabe.
As três causas, em ordem de frequência:
};antes doelse— bloco fechado com ponto e vírgula, como no exemplo;elsesemifacima, geralmente sobra de um refactor que apagou a condição;- uma chave a mais no bloco do
if, que fecha a função inteira antes da hora.
Quando bater esse erro, olhe a linha anterior à que o Node apontou.
Quando o if já não é a ferramenta
O if é instrução: ele executa, não devolve valor. Três situações em que outra
coisa cabe melhor:
- Escolher entre dois valores para atribuir ou interpolar numa string. É o caso do operador ternário, que é expressão e por isso cabe dentro de um template literal.
- Comparar a mesma variável contra muitos valores fixos — status de pedido,
forma de pagamento, sigla de estado. Aí a leitura melhora com
switchou com um objeto de consulta. - Valor padrão quando algo é
nullouundefined.const cupom = entrada ?? 'SEMCUPOM'diz em uma linha o que umifdiz em quatro, e não confunde string vazia com ausência.
A próxima lição da trilha de JavaScript é exatamente o ternário. Se quiser ver onde as condicionais entram no percurso inteiro, o guia completo de JavaScript mostra a ordem de estudo.
Prefere aprender em vídeo?
Tem uma aula sobre este assunto no nosso canal.
Perguntas frequentes
Preciso sempre escrever o else?
Posso usar if sem chaves?
Por que if (0) e if ('') não entram?
Dá para comparar dois objetos dentro de um if?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Node 24.16.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- MDN — if...else — developer.mozilla.org
- MDN — Truthy — developer.mozilla.org



