Identificação
- Duração: 2 horas
- Tipo: teoria aplicada e laboratório
- Entrega: classificador interativo de tarefas
- Laboratório:
../exemplos/aula-2.2/index.html
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:
- explicar o que é fluxo de controle;
- criar condições booleanas explícitas;
- utilizar
if,else ifeelse; - combinar condições com operadores lógicos;
- aplicar o operador ternário em decisões pequenas;
- utilizar
switchpara valores discretos; - diferenciar
for,for...of,whileedo...while; - evitar loops infinitos;
- utilizar
breakecontinueconscientemente; - 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:
ifquando as regras usam intervalos ou expressões diferentes;switchquando 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:
let index = 0: começa em zero;index < 3: repete enquanto for verdadeiro;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...ofpercorre valores de objetos iteráveis, como arrays e strings;for...inpercorre 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
- preencha um título;
- marque urgência e importância;
- selecione um status;
- adicione a tarefa;
- 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:
- a cadeia
if / else if / else; - o
switchque traduz o status; - os loops
for...of; - a condição que mostra o estado vazio;
- 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
elseoudefaultquando 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
ifeswitch. - 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
breakecontinue. - 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
whileprecisa 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.