Condicionais: if, else, switch e operador ternário

1. Fundamentos do if e else

A estrutura if/else é a base do controle de fluxo em JavaScript. Ela permite executar diferentes blocos de código baseados em condições booleanas.

// Estrutura básica do if
const idade = 18;

if (idade >= 18) {
  console.log('Usuário é maior de idade');
}

// Uso do else para caminho alternativo
const usuarioLogado = false;

if (usuarioLogado) {
  console.log('Bem-vindo ao sistema');
} else {
  console.log('Por favor, faça login');
}

// Encadeamento com else if
const nota = 85;

if (nota >= 90) {
  console.log('Classificação: A');
} else if (nota >= 80) {
  console.log('Classificação: B');
} else if (nota >= 70) {
  console.log('Classificação: C');
} else {
  console.log('Classificação: D - Reprovado');
}

2. Truthy e Falsy: A Base das Condicionais em JavaScript

JavaScript realiza coerção implícita de tipos em condicionais. Valores são convertidos para booleanos automaticamente.

// Valores falsy em JavaScript
const valoresFalsy = [false, 0, "", null, undefined, NaN];

valoresFalsy.forEach(valor => {
  if (valor) {
    console.log(`${valor} é truthy`);
  } else {
    console.log(`${valor} é falsy`);
  }
});

// Exemplo prático no Node.js - validação de formulário
function validarEntrada(dados) {
  if (!dados.nome) {
    return 'Nome é obrigatório';
  }

  if (!dados.email) {
    return 'Email é obrigatório';
  }

  if (!dados.idade || dados.idade < 18) {
    return 'Usuário deve ser maior de idade';
  }

  return 'Dados válidos';
}

console.log(validarEntrada({ nome: '', email: 'teste@teste.com', idade: 25 }));
// Saída: "Nome é obrigatório"

3. Switch: Alternativa para Múltiplas Comparações

O switch é ideal quando você precisa comparar uma única variável contra múltiplos valores possíveis.

// Sintaxe completa do switch
const diaSemana = 3;
let nomeDia;

switch (diaSemana) {
  case 1:
    nomeDia = 'Domingo';
    break;
  case 2:
    nomeDia = 'Segunda-feira';
    break;
  case 3:
    nomeDia = 'Terça-feira';
    break;
  case 4:
    nomeDia = 'Quarta-feira';
    break;
  case 5:
    nomeDia = 'Quinta-feira';
    break;
  case 6:
    nomeDia = 'Sexta-feira';
    break;
  case 7:
    nomeDia = 'Sábado';
    break;
  default:
    nomeDia = 'Dia inválido';
}

console.log(nomeDia); // "Terça-feira"

// Fall-through intencional (agrupando casos)
function obterEstacao(mes) {
  let estacao;

  switch (mes) {
    case 12:
    case 1:
    case 2:
      estacao = 'Verão';
      break;
    case 3:
    case 4:
    case 5:
      estacao = 'Outono';
      break;
    case 6:
    case 7:
    case 8:
      estacao = 'Inverno';
      break;
    case 9:
    case 10:
    case 11:
      estacao = 'Primavera';
      break;
    default:
      estacao = 'Mês inválido';
  }

  return estacao;
}

// Exemplo no React - renderização condicional por estado
function ComponentePorEstado({ estado }) {
  switch (estado) {
    case 'carregando':
      return <div>Carregando...</div>;
    case 'erro':
      return <div>Erro ao carregar dados</div>;
    case 'vazio':
      return <div>Nenhum resultado encontrado</div>;
    case 'sucesso':
      return <div>Dados carregados com sucesso!</div>;
    default:
      return null;
  }
}

4. Operador Ternário: Condicional em Expressão Única

O operador ternário permite escrever condicionais em uma única linha, sendo muito útil em JSX.

// Sintaxe básica
const idade = 20;
const podeVotar = idade >= 16 ? 'Pode votar' : 'Não pode votar';
console.log(podeVotar); // "Pode votar"

// Uso em JSX no React
function Saudacao({ usuario }) {
  return (
    <div>
      <h1>
        {usuario ? `Bem-vindo, ${usuario.nome}!` : 'Bem-vindo, visitante!'}
      </h1>
    </div>
  );
}

// Cuidado com ternários aninhados (evitar quando possível)
const status = 'ativo';
const mensagem = 
  status === 'ativo' ? 'Usuário ativo' :
  status === 'inativo' ? 'Usuário inativo' :
  status === 'banido' ? 'Usuário banido' :
  'Status desconhecido';

// Prefira funções auxiliares para múltiplas condições
function obterMensagemStatus(status) {
  if (status === 'ativo') return 'Usuário ativo';
  if (status === 'inativo') return 'Usuário inativo';
  if (status === 'banido') return 'Usuário banido';
  return 'Status desconhecido';
}

5. Condicionais em Node.js: Validação de Dados e Fluxo de Controle

Em aplicações Node.js, condicionais são essenciais para validar requisições e gerenciar fluxos assíncronos.

// Middleware Express com validação condicional
const express = require('express');
const app = express();

function middlewareAutenticacao(req, res, next) {
  const token = req.headers.authorization;

  if (!token) {
    return res.status(401).json({ erro: 'Token não fornecido' });
  }

  if (!token.startsWith('Bearer ')) {
    return res.status(401).json({ erro: 'Formato de token inválido' });
  }

  next();
}

// Tratamento de erros assíncronos
async function buscarUsuario(id) {
  try {
    const usuario = await bancoDeDados.findUser(id);

    if (!usuario) {
      throw new Error('Usuário não encontrado');
    }

    return usuario;
  } catch (erro) {
    console.error(`Erro ao buscar usuário ${id}:`, erro.message);
    throw erro;
  }
}

// Validação de parâmetros com operador ternário
function criarResposta(dados, statusCode = 200) {
  return {
    status: statusCode >= 200 && statusCode < 300 ? 'sucesso' : 'erro',
    dados: dados || null,
    timestamp: new Date().toISOString()
  };
}

6. Condicionais em React: Renderização Condicional de Componentes

React oferece várias formas de renderização condicional usando operadores JavaScript.

// Renderização com && (short-circuit evaluation)
function ListaDeTarefas({ tarefas }) {
  return (
    <div>
      <h2>Minhas Tarefas</h2>
      {tarefas.length > 0 && (
        <ul>
          {tarefas.map(tarefa => (
            <li key={tarefa.id}>{tarefa.nome}</li>
          ))}
        </ul>
      )}
      {tarefas.length === 0 && <p>Nenhuma tarefa encontrada</p>}
    </div>
  );
}

// Função auxiliar com if/else
function PerfilUsuario({ usuario }) {
  function renderizarConteudo() {
    if (!usuario) {
      return <p>Carregando...</p>;
    }

    if (usuario.bloqueado) {
      return <p>Usuário bloqueado</p>;
    }

    return (
      <div>
        <h3>{usuario.nome}</h3>
        <p>Email: {usuario.email}</p>
      </div>
    );
  }

  return <div className="perfil">{renderizarConteudo()}</div>;
}

// Combinação de ternário com map()
function GaleriaDeImagens({ imagens, modoVisualizacao }) {
  return (
    <div className={`galeria ${modoVisualizacao}`}>
      {imagens.map(imagem => (
        <div key={imagem.id} className="item">
          <img src={imagem.url} alt={imagem.titulo} />
          <p>
            {modoVisualizacao === 'compacto' 
              ? imagem.titulo.substring(0, 20) + '...'
              : imagem.titulo}
          </p>
        </div>
      ))}
    </div>
  );
}

7. Boas Práticas e Armadilhas Comuns

// ❌ Evite: condicionais profundamente aninhadas
function processarPedido(pedido, usuario) {
  if (usuario) {
    if (usuario.ativo) {
      if (pedido) {
        if (pedido.itens.length > 0) {
          // processar pedido
        }
      }
    }
  }
}

// ✅ Prefira: early return pattern
function processarPedido(pedido, usuario) {
  if (!usuario) return { erro: 'Usuário não autenticado' };
  if (!usuario.ativo) return { erro: 'Usuário inativo' };
  if (!pedido) return { erro: 'Pedido não encontrado' };
  if (pedido.itens.length === 0) return { erro: 'Pedido vazio' };

  // processar pedido
  return { sucesso: true };
}

// ❌ Evite: usar == em vez de ===
if (0 == false) { // true - coerção implícita
  console.log('Isso executa, mas é perigoso');
}

// ✅ Use sempre ===
if (0 === false) { // false - comparação estrita
  console.log('Isso não executa');
}

// Performance: objeto de lookup vs switch vs if/else
const acoes = {
  'criar': (dados) => criarUsuario(dados),
  'atualizar': (dados) => atualizarUsuario(dados),
  'deletar': (id) => deletarUsuario(id),
  'listar': () => listarUsuarios()
};

function executarAcao(tipo, dados) {
  const acao = acoes[tipo];
  return acao ? acao(dados) : { erro: 'Ação inválida' };
}

8. Exemplo Prático Integrado: Sistema de Autenticação

// Parte 1: Node.js - Validação de formulário de login
function validarLogin(email, senha) {
  if (!email || !senha) {
    return { valido: false, erro: 'Email e senha são obrigatórios' };
  }

  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(email)) {
    return { valido: false, erro: 'Formato de email inválido' };
  }

  if (senha.length < 6) {
    return { valido: false, erro: 'Senha deve ter no mínimo 6 caracteres' };
  }

  return { valido: true };
}

// Parte 2: React - Renderização condicional com operador ternário
function PaginaInicial({ usuario }) {
  return (
    <div className="app">
      {usuario ? (
        <Dashboard usuario={usuario} />
      ) : (
        <TelaLogin onLogin={handleLogin} />
      )}
    </div>
  );
}

// Parte 3: Tratamento de papéis com switch
function Dashboard({ usuario }) {
  function renderizarConteudoPorPapel() {
    switch (usuario.papel) {
      case 'admin':
        return (
          <div>
            <PainelAdmin />
            <GerenciarUsuarios />
          </div>
        );
      case 'editor':
        return (
          <div>
            <PainelEditor />
            <GerenciarConteudo />
          </div>
        );
      case 'visitante':
        return (
          <div>
            <ConteudoPublico />
          </div>
        );
      default:
        return <p>Acesso não autorizado</p>;
    }
  }

  return (
    <div className="dashboard">
      <h1>Bem-vindo, {usuario.nome}!</h1>
      {renderizarConteudoPorPapel()}
    </div>
  );
}

Referências