Estrutura condicional: se, senão e senão se no algoritmo
A decisão que o programa toma sozinho: condição simples, composta e encadeada, com a faixa de desconto errada aparecendo na saída antes da correção.
Estrutura condicional escolhe qual trecho do algoritmo executar a partir de uma condição verdadeira ou falsa. O desafio não é escrever if; é formular perguntas sem sobreposição e ordenar os caminhos para que todos os valores recebam a regra certa.
O domínio é o desconto de uma papelaria. Antes de escolher, o programa calcula expressões booleanas; por isso vale revisar operadores e expressões.
A pergunta que só aceita sim ou não
Uma condição não responde “talvez”. Ela se reduz a true ou false:
const total = 120;
const atingiuMinimo = total >= 100;
console.log(atingiuMinimo);
if (atingiuMinimo) console.log('cupom liberado');Pense numa catraca que abre quando uma regra é satisfeita. O limite da analogia é que código pode ter efeitos diferentes em cada lado e condições compostas; a catraca apenas ajuda a visualizar a bifurcação.
Se sem senão: quando não fazer nada é válido
Uma compra sem cupom não precisa de mensagem extra. O if executa somente para quem tem cupom:
function aplicarCupom(total, cupom) {
if (cupom === 'VOLTA10') total *= 0.9;
return total;
}
console.log(aplicarCupom(100, 'VOLTA10'));
console.log(aplicarCupom(100, ''));O caminho falso não ficou indefinido: ele preserva o total e chega ao return. Um else seria necessário se o requisito exigisse registrar “cupom recusado”.
Senão se: uma escada de faixas
A regra correta é 15% a partir de R$ 2.000, 10% a partir de R$ 1.000 e 5% a partir de R$ 100. A versão errada testa a menor faixa primeiro:
function descontoErrado(total) {
if (total >= 100) return 5;
if (total >= 1000) return 10;
if (total >= 2000) return 15;
return 0;
}
console.log(descontoErrado(2000));Não há erro de sintaxe. A primeira condição já é verdadeira para 2.000, então a função retorna antes de consultar as demais. Esse é o bug da faixa sobreposta.
A tabela de seis bordas revela onde a ordem diverge
Teste logo abaixo e exatamente nos limites:
function descontoErrado(total) {
if (total >= 100) return 5;
if (total >= 1000) return 10;
if (total >= 2000) return 15;
return 0;
}
for (const total of [99, 100, 999, 1000, 1999, 2000]) {
console.log(total, descontoErrado(total));
}Os três últimos resultados expõem a sobreposição. Um caso comum de 100 passaria e daria falsa confiança.
Corrija começando pela condição mais restritiva
Quando faixas usam “maior ou igual”, teste do maior limite para o menor:
function desconto(total) {
if (total >= 2000) return 15;
if (total >= 1000) return 10;
if (total >= 100) return 5;
return 0;
}
for (const total of [99, 100, 999, 1000, 1999, 2000]) {
console.log(total, desconto(total));
}Agora cada entrada cai na primeira faixa que a contém. A tabela autoral de seis casos é o critério de acerto, não apenas “parece funcionar”.
Condição aninhada: o segundo teste depende do primeiro
Uma análise antifraude só deve acontecer depois que o pagamento foi autorizado:
function decidirPedido(pagamentoAutorizado, riscoAlto) {
if (pagamentoAutorizado) {
if (riscoAlto) return 'revisão manual';
return 'separar pedido';
}
return 'aguardar pagamento';
}
console.log(decidirPedido(false, true));
console.log(decidirPedido(true, true));
console.log(decidirPedido(true, false));O aninhamento expressa dependência. Se as perguntas forem independentes, condições compostas ou retornos antecipados podem ficar mais claros. Mais de dois níveis é sinal para decompor uma função.
Quando a escada pede uma tabela
Se a entrada é uma chave exata, uma tabela evita uma sequência de comparações:
const prazoPorRegiao = {
sudeste: 2,
sul: 3,
nordeste: 5,
};
function prazo(regiao) {
return prazoPorRegiao[regiao] ?? 7;
}
console.log(prazo('sul'));
console.log(prazo('norte'));Aqui não existe intervalo nem prioridade. Existe associação de região para prazo. Acrescentar uma chave não mexe no fluxo de controle.
Tire a negação dupla da leitura
if (!naoEstaBloqueado) exige duas inversões mentais. Nomeie o estado positivo:
const naoEstaBloqueado = true;
const acessoPermitido = naoEstaBloqueado;
if (acessoPermitido) console.log('entrar');
else console.log('bloquear');Não alteramos a lógica, apenas o vocabulário. Nomes positivos deixam operadores de negação disponíveis para regras que realmente precisam inverter um estado.
Missão: frete grátis nas bordas
Implemente estas regras: membros têm frete grátis a partir de R$ 80; demais clientes, a partir de R$ 150; região remota nunca recebe gratuidade. Antes do JavaScript, desenhe os caminhos e escreva os casos de borda.
function freteGratis(total, membro, regiaoRemota) {
if (regiaoRemota) return false;
if (membro) return total >= 80;
return total >= 150;
}
console.log([79, 80, 149, 150].map((total) => [total, freteGratis(total, true, false), freteGratis(total, false, false)]));Antes de considerar a regra pronta, monte uma matriz de decisões. Varie total, associação e região separadamente. Se dois casos têm a mesma saída por motivos diferentes, anote qual condição decidiu; isso impede que uma condição anterior esconda outra que nunca executa.
Retornos antecipados funcionam bem para exceções e bloqueios: região remota encerra a decisão antes das faixas. A ordem precisa refletir prioridade de negócio, não preferência estética. Se amanhã existir exceção para retirada na loja, descubra se ela vem antes ou depois do bloqueio remoto e transforme a resposta em caso de teste.
Condições também precisam de cobertura negativa. Para cada caminho aprovado, procure a menor mudança capaz de negar: reduzir um centavo, remover associação ou marcar região. Essa dupla de casos confirma que a condição é responsável pela diferença observada.
Quando uma escada passa de muitas faixas e muda com frequência, mova limites para dados validados ou uma tabela de decisão. Ainda será necessário código para encontrar a faixa, mas a política deixa de ficar espalhada por comparações. Não faça a migração cedo: três faixas estáveis continuam legíveis como retornos ordenados.
Por fim, leia as condições em voz alta usando o vocabulário do requisito. Se o texto diz “clientes não bloqueados” e o código exige duas negações, crie um nome positivo intermediário. Código que pode ser lido como a regra é mais fácil de revisar nas bordas.
Registre a tabela de casos ao lado da mudança de política. Ela funciona como contrato de regressão: uma nova exceção precisa adicionar ou alterar casos conscientemente, não apenas fazer a execução atual parecer correta.
Termine quando explicar por que região remota é testada primeiro. Depois use a tabela verdade para conferir combinações, rastreie as bordas com o teste de mesa e siga a sequência do guia de lógica pela trilha completa.
Perguntas frequentes
Todo if precisa de else?
Quando substituir vários else if por uma tabela?
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 v26.3.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- ECMAScript — If Statement — tc39.es
- ECMAScript — Conditional Operator — tc39.es


