Engenharia de IA Aplicada à Programação Web
Aula 2 de 8
Navegar por módulos e aulas
  1. 01 Fundamentos da Web
  2. 02 JavaScript moderno
  3. 03 TypeScript, Git e qualidade
  4. 04 Angular
  5. 05 Node.js, NestJS e APIs
  1. 2.1 Valores, variáveis e tipos
  2. 2.2 Condições e repetições
  3. 2.3 Funções, escopo e closures
  4. 2.4 Arrays e transformação de dados
  5. 2.5 Objetos, JSON e modelagem
  6. 2.6 Módulos e tratamento de erros
  7. 2.7 Promises, async/await e Fetch
  8. 2.8 Armazenamento, testes e projeto

Módulo 2 · Aula 2.2

Condições e repetições

2 horas Teoria + laboratório JavaScript moderno
Ver fonte Markdown

Identificação

Introdução

Por que um programa precisa tomar decisões?

Um programa raramente executa sempre exatamente o mesmo caminho. Ele precisa observar os dados e decidir o que fazer:

  • se o formulário estiver inválido, mostrar uma orientação;
  • se o usuário estiver autenticado, liberar a área privada;
  • se uma tarefa for urgente e importante, classificá-la como prioridade crítica;
  • se não houver tarefas, apresentar um estado vazio.

Em JavaScript, representamos essas decisões principalmente com if, else if, else e switch.

const isFormValid = true;

if (isFormValid) {
  console.log("O formulário pode ser enviado.");
} else {
  console.log("Revise os campos.");
}

O que é uma condição?

Uma condição é uma expressão analisada como verdadeira ou falsa. O resultado orienta qual trecho do programa será executado.

const remainingDays = 2;
const isUrgent = remainingDays <= 2;

if (isUrgent) {
  console.log("Prioridade alta");
}

Não confunda condição com repetição:

  • uma condição escolhe um caminho;
  • uma repetição executa uma ação várias vezes enquanto uma regra permitir.

Por que repetir instruções?

Imagine que existam cinquenta tarefas. Escrever cinquenta comandos manualmente não seria sustentável. Uma estrutura de repetição, também chamada de loop ou laço, percorre os dados:

const tasks = ["Estudar JavaScript", "Revisar HTML", "Publicar projeto"];

for (const task of tasks) {
  console.log(task);
}

O loop não cria dados sozinho. Ele define como o programa visita uma sequência ou repete uma operação.

Preciso decorar todos os tipos de loop?

Não. O mais importante é reconhecer a intenção:

  • for...of: percorrer valores de uma coleção;
  • for: controlar índice, início, limite e incremento;
  • while: repetir enquanto uma condição for verdadeira;
  • do...while: executar ao menos uma vez e depois verificar;
  • métodos de arrays, estudados na Aula 2.4, expressam transformações comuns.

Onde isso aparece no projeto?

Nesta aula construiremos um classificador de tarefas. Cada tarefa passará por condições que determinam sua prioridade. Depois, um loop atualizará a lista e as métricas exibidas na página.

Objetivos

Ao final da aula, o aluno deverá conseguir:

  1. explicar o que é fluxo de controle;
  2. criar condições booleanas explícitas;
  3. utilizar if, else if e else;
  4. combinar condições com operadores lógicos;
  5. aplicar o operador ternário em decisões pequenas;
  6. utilizar switch para valores discretos;
  7. diferenciar for, for...of, while e do...while;
  8. evitar loops infinitos;
  9. utilizar break e continue conscientemente;
  10. classificar e percorrer tarefas em uma interface.

Pré-requisitos

  • Aula 2.1 concluída;
  • conhecimento de valores, tipos, comparações e operadores lógicos;
  • navegador, DevTools e editor de código;
  • noções de eventos e manipulação do DOM vistas no Módulo 1.

Pergunta orientadora

Como fazer o programa escolher caminhos e processar vários itens sem duplicar código?

Roteiro sugerido

Etapa Duração
Introdução e fluxo de controle 15 min
Condições com if e operadores lógicos 30 min
switch e operador ternário 15 min
Estruturas de repetição 30 min
Laboratório 25 min
Revisão 5 min

1. Fluxo de controle

O código é lido normalmente de cima para baixo. Estruturas de controle alteram esse fluxo:

const hasPermission = false;

console.log("Início");

if (hasPermission) {
  console.log("Área privada");
}

console.log("Fim");

Como hasPermission é false, a linha dentro do bloco não é executada.

Um bloco é delimitado por chaves:

if (condition) {
  // bloco executado quando a condição for verdadeira
}

Mesmo quando existe apenas uma instrução, mantenha as chaves. Elas tornam o limite da decisão visível e reduzem erros durante futuras alterações.

2. if, else if e else

Uma decisão

const taskIsLate = true;

if (taskIsLate) {
  console.log("Tarefa atrasada");
}

Dois caminhos

const isAuthenticated = false;

if (isAuthenticated) {
  console.log("Abrir painel");
} else {
  console.log("Solicitar login");
}

Vários caminhos

const score = 82;

if (score >= 90) {
  console.log("Excelente");
} else if (score >= 70) {
  console.log("Aprovado");
} else {
  console.log("Revisão necessária");
}

A ordem importa. O primeiro teste verdadeiro encerra a cadeia. Por isso, nesse caso verificamos primeiro a maior nota.

3. Condições claras

Prefira nomes que revelem o significado da regra:

const remainingDays = 1;
const isUrgent = remainingDays <= 2;
const hasDeadline = remainingDays >= 0;

if (hasDeadline && isUrgent) {
  console.log("Tratar com prioridade");
}

Isso costuma ser mais claro que concentrar tudo em uma expressão longa:

if (remainingDays >= 0 && remainingDays <= 2) {
  console.log("Tratar com prioridade");
}

As duas versões funcionam. A primeira facilita explicar e testar a regra.

4. Operadores lógicos nas decisões

E lógico: &&

Todas as condições precisam ser verdadeiras:

if (isUrgent && isImportant) {
  console.log("Faça agora");
}

OU lógico: ||

Ao menos uma condição precisa ser verdadeira:

if (isLate || isBlocked) {
  console.log("Requer atenção");
}

Negação: !

Inverte o valor booleano:

if (!hasTitle) {
  console.log("Informe um título");
}

Use parênteses quando eles tornarem a intenção mais evidente:

if (isActive && (isAdmin || isOwner)) {
  console.log("Acesso permitido");
}

5. Truthy e falsy em condições

Uma condição não precisa receber literalmente true ou false. JavaScript converte outros valores para booleano:

const title = "";

if (title) {
  console.log("Existe um título");
}

Como string vazia é falsy, o bloco não é executado.

Para regras importantes, deixe a intenção explícita:

const hasTitle = title.trim().length > 0;

if (!hasTitle) {
  console.log("O título é obrigatório");
}

Isso evita confundir valores válidos como 0 com ausência de valor.

6. Comparar não é atribuir

Observe os operadores:

const status = "done"; // atribuição durante a declaração

if (status === "done") { // comparação estrita
  console.log("Concluída");
}

Dentro de condições, prefira === e !==. Um sinal de igual isolado atribui um valor; não representa uma comparação.

7. Operador ternário

O ternário representa uma escolha curta que produz um valor:

const label = isUrgent ? "Urgente" : "Normal";

Sua estrutura é:

condição ? valor_se_verdadeira : valor_se_falsa

Use-o para decisões pequenas. Para regras com vários passos, prefira if:

let priority;

if (isUrgent && isImportant) {
  priority = "critical";
} else if (isUrgent) {
  priority = "high";
} else {
  priority = "normal";
}

Ternários aninhados rapidamente ficam difíceis de ler.

8. switch

switch é útil quando uma mesma expressão pode ter valores discretos:

const status = "doing";

switch (status) {
  case "todo":
    console.log("A fazer");
    break;
  case "doing":
    console.log("Em andamento");
    break;
  case "done":
    console.log("Concluída");
    break;
  default:
    console.log("Status desconhecido");
}

O break encerra o switch. Sem ele, a execução continua no próximo case, comportamento chamado de fall-through.

Use:

  • if quando as regras usam intervalos ou expressões diferentes;
  • switch quando comparamos uma expressão a alternativas conhecidas.

9. Repetição com for

O for reúne inicialização, condição e atualização:

for (let index = 0; index < 3; index += 1) {
  console.log(index);
}

Leitura:

  1. let index = 0: começa em zero;
  2. index < 3: repete enquanto for verdadeiro;
  3. index += 1: aumenta o índice ao final de cada volta.

Saída:

0
1
2

Arrays começam no índice zero:

const tasks = ["Estudar", "Praticar", "Revisar"];

for (let index = 0; index < tasks.length; index += 1) {
  console.log(index, tasks[index]);
}

10. Repetição com for...of

Quando precisamos dos valores, e não do índice, for...of costuma ser mais simples:

const tasks = ["Estudar", "Praticar", "Revisar"];

for (const task of tasks) {
  console.log(task);
}

Não confunda:

  • for...of percorre valores de objetos iteráveis, como arrays e strings;
  • for...in percorre nomes de propriedades enumeráveis e não é a escolha usual para percorrer valores de arrays.

11. Repetição com while

while repete enquanto a condição for verdadeira:

let attempts = 0;

while (attempts < 3) {
  console.log(`Tentativa ${attempts + 1}`);
  attempts += 1;
}

Ele é útil quando não sabemos antecipadamente quantas repetições serão necessárias, mas sabemos qual condição deve encerrar o processo.

Risco de loop infinito

Este código nunca altera attempts:

let attempts = 0;

while (attempts < 3) {
  console.log(attempts);
}

A condição permanece verdadeira indefinidamente. Antes de escrever um while, responda:

O que muda a cada volta e como a condição se tornará falsa?

12. Repetição com do...while

do...while executa o bloco pelo menos uma vez:

let option;

do {
  option = "continue";
} while (option === "retry");

A condição é verificada depois do bloco. Em interfaces web, eventos frequentemente substituem a necessidade desse tipo de loop, pois cada nova interação do usuário dispara outra execução.

13. break e continue

break

Encerra o loop:

for (const task of tasks) {
  if (task.id === searchedId) {
    console.log("Tarefa encontrada");
    break;
  }
}

continue

Pula apenas a volta atual:

for (const task of tasks) {
  if (task.status === "done") {
    continue;
  }

  console.log(task.title);
}

Use ambos com moderação. Muitos desvios dentro do loop dificultam acompanhar o fluxo.

14. Regra do classificador

O laboratório utiliza urgência e importância:

Urgente Importante Classificação Orientação
sim sim crítica faça agora
sim não alta resolva ou delegue
não sim planejada reserve um horário
não não baixa reavalie a necessidade

Uma implementação direta:

let priority;

if (isUrgent && isImportant) {
  priority = "critical";
} else if (isUrgent) {
  priority = "high";
} else if (isImportant) {
  priority = "planned";
} else {
  priority = "low";
}

O laboratório também utiliza switch para traduzir o status e for...of para renderizar as tarefas e calcular métricas.

15. Laboratório guiado

Abra o classificador de tarefas.

Etapa 1 — Observe a decisão

  1. preencha um título;
  2. marque urgência e importância;
  3. selecione um status;
  4. adicione a tarefa;
  5. compare a classificação com a tabela de regras.

Etapa 2 — Observe a repetição

Adicione mais tarefas. A cada mudança, o programa percorre a coleção para:

  • criar os cartões visuais;
  • contar o total;
  • contar prioridades críticas;
  • contar tarefas concluídas.

Etapa 3 — Inspecione o código

Abra assets/main.js e localize:

  1. a cadeia if / else if / else;
  2. o switch que traduz o status;
  3. os loops for...of;
  4. a condição que mostra o estado vazio;
  5. a validação do título.

Etapa 4 — Faça uma alteração

Adicione uma regra visual para tarefas com duração maior que quatro horas. Antes de editar, escreva a condição em português:

Se a estimativa for maior que quatro horas, mostrar “Divida em partes menores”.

Depois transforme-a em JavaScript.

16. Erros comuns

Usar atribuição no lugar de comparação

if (status = "done") {
  // incorreto para comparar
}

Use:

if (status === "done") {
}

Criar condições impossíveis

if (score < 0 && score > 100) {
}

Um mesmo número não pode ser simultaneamente menor que zero e maior que cem.

Errar o limite do loop

for (let index = 0; index <= tasks.length; index += 1) {
  console.log(tasks[index]);
}

O último índice válido é length - 1. Portanto:

for (let index = 0; index < tasks.length; index += 1) {
}

Alterar a coleção durante a repetição sem planejamento

Adicionar ou remover itens do mesmo array que está sendo percorrido pode mudar índices e produzir resultados inesperados. Primeiro compreenda a regra; na Aula 2.4 veremos transformações imutáveis.

Bloquear a página com um loop

JavaScript da interface normalmente executa na thread principal. Um loop infinito impede cliques, desenho e outras interações. Se a aba travar durante um exercício, interrompa a execução pelo DevTools e revise a condição de saída.

17. Boas práticas

  • dê nomes claros às condições;
  • prefira comparações estritas;
  • ordene cadeias de decisão do caso específico para o geral;
  • mantenha um else ou default quando existir um caso de fallback;
  • deixe visível como o loop termina;
  • evite duplicar a mesma regra em vários lugares;
  • teste limites: zero, vazio, primeiro item, último item e valor máximo;
  • não use loops longos para bloquear deliberadamente a interface.

18. Exercícios

Exercício 1 — Faixa de estimativa

Classifique uma tarefa:

  • até 1 hora: curta;
  • acima de 1 e até 4 horas: média;
  • acima de 4 horas: longa.

Exercício 2 — Contagem

Crie um loop que conte quantas tarefas ainda não estão concluídas.

Exercício 3 — Busca

Percorra uma lista e interrompa o loop com break quando encontrar uma tarefa pelo identificador.

Exercício 4 — Validação

Rejeite títulos vazios ou formados apenas por espaços.

Exercício 5 — Regra combinada

Marque como “atenção” uma tarefa que esteja atrasada ou bloqueada, desde que ela ainda não esteja concluída.

19. Desafio

Acrescente ao laboratório:

  • filtro por prioridade;
  • botão para concluir uma tarefa;
  • mensagem específica para tarefas longas;
  • contador de tarefas em andamento;
  • teste manual documentado para cada combinação de urgência e importância.

Não utilize innerHTML para inserir dados do usuário. Crie elementos e atribua conteúdo com textContent.

20. Lista de verificação de conclusão

  • Sei explicar condição e repetição com minhas palavras.
  • Consigo escolher entre if e switch.
  • Entendo a ordem de uma cadeia else if.
  • Consigo usar &&, || e ! em regras.
  • Sei quando um ternário fica complexo demais.
  • Consigo percorrer valores com for...of.
  • Sei identificar a condição de saída de um while.
  • Entendo os efeitos de break e continue.
  • Testei as quatro combinações do classificador.
  • Inspecionei a interface pelo DevTools.

21. Critérios de avaliação

Critério Pontos
Condições corretas e legíveis 30
Repetição e métricas 25
Validação e estados da interface 20
Acessibilidade e segurança do DOM 15
Explicação das escolhas 10
Total 100

Resumo

Nesta aula, aprendemos que:

  • condições escolhem caminhos;
  • loops repetem operações;
  • a ordem das regras altera o resultado;
  • for...of é uma opção clara para percorrer valores;
  • todo while precisa de uma condição que possa se tornar falsa;
  • interfaces devem comunicar validação, estado vazio e resultado;
  • regras legíveis são mais fáceis de testar e manter.

Próxima aula

Na Aula 2.3, organizaremos regras em funções, entenderemos parâmetros e retorno e estudaremos como escopo e closures controlam o acesso aos valores.