O Poder da Repetição

Imagine que você precisa exibir na tela todos os números de 1 até 100. Sem o conhecimento de estruturas de repetição, você precisaria escrever 100 linhas de código, algo como:

console.log(1);
console.log(2);
console.log(3);
// ... 97 linhas depois...
console.log(100);

Além de entediante e demorado, esse código seria extremamente difícil de manter. E se você precisasse mudar para 1000 números? Ou se quisesse alterar o formato de exibição?

É aqui que entram as estruturas de repetição - os loops. Eles são fundamentais na programação porque permitem executar o mesmo código múltiplas vezes de forma eficiente, automatizando tarefas repetitivas que seriam impraticáveis de fazer manualmente.

Com loops, aquelas 100 linhas se tornam apenas 3:

for (let i = 1; i <= 100; i++) {
    console.log(i);
}

Muito mais elegante, não é?

Por Que Usar Loops?

Linguagens de programação são extremamente úteis para completar rapidamente tarefas repetitivas. Os loops resolvem o problema fundamental da repetição de código, tornando nossos programas:

1. Mais Concisos

Menos código para escrever e manter significa menos oportunidades para erros e mais facilidade de compreensão.

2. Mais Flexíveis

É fácil modificar o número de repetições ou o comportamento do loop. Quer processar 10 ou 10.000 itens? Basta mudar um número!

3. Mais Eficientes

Evitamos duplicação desnecessária de código. Uma única lógica bem escrita pode ser executada quantas vezes necessário.

4. Menos Propensos a Erros

Uma única implementação correta elimina a possibilidade de erros de cópia e cola que poderiam surgir ao duplicar código manualmente.

O Conceito Fundamental: Repetição Controlada

Todos os loops, independentemente de sua sintaxe específica, compartilham um conceito fundamental: execução repetitiva controlada por uma condição de parada.

Pense nos loops como um conjunto de instruções que você segue repetidamente até que uma condição específica seja satisfeita. É como uma receita que diz "continue batendo os ovos até que a mistura fique homogênea" - você repete a ação até alcançar o resultado desejado.

Componentes Essenciais de Todo Loop

Embora a sintaxe varie, todos os loops precisam de três elementos:

  1. Inicialização: Configurar o ponto de partida
  2. Condição: Determinar quando parar
  3. Atualização: Modificar algo para eventualmente satisfazer a condição de parada

Vamos explorar como cada tipo de loop implementa esses conceitos.


Os Três Tipos Principais de Loops em JavaScript

JavaScript oferece três estruturas principais de repetição, cada uma adequada para situações específicas. Embora sejam amplamente intercambiáveis, entender suas particularidades ajuda a escolher a ferramenta certa para cada trabalho.

1. Loop while - Repetição Baseada em Condição

O loop while é o mais simples conceitualmente. Ele diz: "enquanto esta condição for verdadeira, continue executando este código."

Sintaxe Básica

while (condição) {
    // código a ser executado
}

Estrutura Completa

// 1. INICIALIZAÇÃO (antes do loop)
let contador = 0;

// 2. CONDIÇÃO (testada antes de cada execução)
while (contador < 5) {
    console.log("Número: " + contador);
    
    // 3. ATUALIZAÇÃO (dentro do loop)
    contador++;
}

Saída:

Número: 0
Número: 1
Número: 2
Número: 3
Número: 4

Como o while Funciona

O loop while verifica a condição antes de cada iteração. Se a condição for verdadeira, o código é executado. Se for falsa, o loop termina imediatamente.

Fluxograma mental:

  1. Verificar condição
  2. Se verdadeira → executar código → voltar ao passo 1
  3. Se falsa → sair do loop

Quando Usar while

O while é ideal quando:

  • Você não sabe exatamente quantas iterações serão necessárias
  • A condição de parada depende de algo que acontece durante a execução
  • A lógica é mais clara expressando "enquanto isso for verdade"

Exemplo Prático: Validação de Entrada

let senha = "";
let tentativas = 0;
const senhaCorreta = "javascript123";

while (senha !== senhaCorreta && tentativas < 3) {
    senha = prompt("Digite a senha:");
    tentativas++;
    
    if (senha === senhaCorreta) {
        console.log("Acesso permitido!");
    } else if (tentativas < 3) {
        console.log("Senha incorreta. Tente novamente.");
    } else {
        console.log("Número máximo de tentativas excedido.");
    }
}

⚠️ Cuidado com Loops Infinitos!

Um dos erros mais comuns ao usar while é esquecer de atualizar a condição, criando um loop infinito que nunca termina:

// ❌ EVITE ISSO - Loop infinito!
let i = 0;
while (i < 5) {
    console.log(i);
    // Esqueceu de incrementar i!
}

Por que loops infinitos são problemáticos? Eles podem travar completamente seu programa ou navegador, pois o código nunca satisfaz a condição de parada. O programa fica "preso" executando o mesmo código indefinidamente.

Solução: Sempre certifique-se de que algo dentro do loop eventualmente tornará a condição falsa:

// ✅ CORRETO
let i = 0;
while (i < 5) {
    console.log(i);
    i++; // Incrementa i, aproximando-se da condição de parada
}

Loop do...while - Execute Primeiro, Pergunte Depois

O do...while é uma variação do while com uma diferença crucial: ele garante que o código seja executado pelo menos uma vez, pois a verificação da condição acontece no final, não no início.

Sintaxe Básica

do {
    // código a ser executado
} while (condição);

Estrutura Completa

let contador = 0;

do {
    console.log("Número: " + contador);
    contador++;
} while (contador < 5);

A Diferença Fundamental

while: Testa a condição antes da primeira execução

  • Se a condição for falsa desde o início, o código nunca executa

do...while: Testa a condição depois da primeira execução

  • O código sempre executa pelo menos uma vez, mesmo se a condição for falsa

Comparação Prática

// Exemplo 1: while
let x = 10;
while (x < 5) {
    console.log("Este código nunca será executado");
}
// Saída: (nada)

// Exemplo 2: do...while
let y = 10;
do {
    console.log("Este código será executado uma vez");
} while (y < 5);
// Saída: Este código será executado uma vez

Quando Usar do...while

O do...while é perfeito para situações onde você precisa:

  • Executar o código pelo menos uma vez antes de verificar se deve continuar
  • Coletar entrada do usuário e validá-la depois
  • Garantir uma primeira execução independente da condição

Exemplo Prático: Menu Interativo

let opcao;

do {
    console.log("\n=== MENU PRINCIPAL ===");
    console.log("1. Ver saldo");
    console.log("2. Fazer depósito");
    console.log("3. Fazer saque");
    console.log("4. Sair");
    
    opcao = prompt("Escolha uma opção:");
    
    // Processar opção escolhida
    switch(opcao) {
        case "1":
            console.log("Saldo: R$ 1.500,00");
            break;
        case "2":
            console.log("Depósito realizado");
            break;
        case "3":
            console.log("Saque realizado");
            break;
        case "4":
            console.log("Até logo!");
            break;
        default:
            console.log("Opção inválida");
    }
    
} while (opcao !== "4");

Neste exemplo, queremos mostrar o menu pelo menos uma vez, independentemente de qualquer condição prévia. O do...while é perfeito para isso.

Loop for - O Loop Mais Concentrado

O loop for é considerado o mais "concentrado" porque reúne todos os três componentes essenciais (inicialização, condição e atualização) em uma única declaração. É o loop mais comumente usado, especialmente quando você sabe exatamente quantas iterações precisa.

Sintaxe Básica

for (inicialização; condição; expressão-final) {
    // código a ser executado
}

Estrutura Detalhada

for (let i = 0; i < 5; i++) {
    console.log("Iteração: " + i);
}

Vamos dissecar cada parte:

  1. let i = 0 (Inicialização)

    • Executado uma única vez antes do loop começar
    • Define o ponto de partida
    • Normalmente cria a variável de controle
  2. i < 5 (Condição)

    • Testada antes de cada iteração
    • Se verdadeira, o código executa
    • Se falsa, o loop termina
  3. i++ (Expressão Final)

    • Executada depois de cada iteração
    • Normalmente atualiza a variável de controle
    • Aproxima a condição do ponto de término

Como o for Funciona - Passo a Passo

Vamos acompanhar em detalhes a execução de um loop for:

for (let i = 0; i < 3; i++) {
    console.log("Valor de i: " + i);
}

Execução:

  1. Antes do loop: let i = 0 → i recebe 0

  2. Iteração 1:

    • Verificar: i < 3? (0 < 3?) → Sim ✓
    • Executar: console.log("Valor de i: 0")
    • Atualizar: i++ → i se torna 1
  3. Iteração 2:

    • Verificar: i < 3? (1 < 3?) → Sim ✓
    • Executar: console.log("Valor de i: 1")
    • Atualizar: i++ → i se torna 2
  4. Iteração 3:

    • Verificar: i < 3? (2 < 3?) → Sim ✓
    • Executar: console.log("Valor de i: 2")
    • Atualizar: i++ → i se torna 3
  5. Tentativa de Iteração 4:

    • Verificar: i < 3? (3 < 3?) → Não ✗
    • Loop termina

Saída:

Valor de i: 0
Valor de i: 1
Valor de i: 2

Variações do Loop for

Uma característica interessante do for é que qualquer uma de suas partes pode ser omitida (embora isso seja raro na prática):

// Inicializador externo
let i = 0;
for (; i < 3; i++) {
    console.log(i);
}

// Sem incremento automático
let j = 0;
for (; j < 3;) {
    console.log(j);
    j++;
}

// Loop infinito (use com MUITO cuidado!)
for (;;) {
    console.log("Este é um loop infinito");
    break; // necessário para sair!
}

Quando Usar for

O for é ideal quando:

  • Você sabe exatamente quantas iterações são necessárias
  • Precisa de um contador explícito
  • Trabalha com arrays e índices numéricos
  • Quer toda a lógica de controle visível em um só lugar

Exemplos Práticos

Exemplo 1: Contagem Regressiva

console.log("Iniciando contagem regressiva:");

for (let i = 10; i >= 1; i--) {
    console.log(i);
}

console.log("Lançamento! 🚀");

Saída:

Iniciando contagem regressiva:
10
9
8
7
6
5
4
3
2
1
Lançamento! 🚀

Exemplo 2: Calculando Fatorial

let numero = 5;
let fatorial = 1;

for (let i = 1; i <= numero; i++) {
    fatorial = fatorial * i;
    console.log(`${i}! = ${fatorial}`);
}

console.log(`\nO fatorial de ${numero} é ${fatorial}`);

Saída:

1! = 1
2! = 2
3! = 6
4! = 24
5! = 120

O fatorial de 5 é 120

Exemplo 3: Criando Padrões Visuais

// Criando um triângulo de asteriscos
let altura = 5;

for (let i = 1; i <= altura; i++) {
    let linha = "";
    
    for (let j = 1; j <= i; j++) {
        linha += "* ";
    }
    
    console.log(linha);
}

Saída:

* 
* * 
* * * 
* * * * 
* * * * * 

Este exemplo demonstra loops aninhados - um loop dentro de outro. O loop externo controla as linhas, enquanto o loop interno controla quantos asteriscos em cada linha.

Exemplo 4: Soma de Números em Intervalo

let inicio = 1;
let fim = 10;
let soma = 0;

for (let i = inicio; i <= fim; i++) {
    soma += i;
}

console.log(`A soma dos números de ${inicio} a ${fim} é: ${soma}`);

Saída:

A soma dos números de 1 a 10 é: 55

Controlando o Fluxo: break e continue

Às vezes, você precisa de controle mais fino sobre a execução do loop. JavaScript fornece duas instruções especiais para isso: break e continue.

Instrução break - Sair Completamente

A instrução break permite sair de um loop imediatamente, independentemente da condição. É como encontrar o que você procura e não precisar continuar procurando.

Sintaxe

for (let i = 0; i < 10; i++) {
    if (i === 5) {
        break; // Para o loop quando i for igual a 5
    }
    console.log(i);
}

Saída:

0
1
2
3
4

Note que 5 e os números seguintes não são exibidos - o loop terminou quando i chegou a 5.

Exemplo Prático: Busca em Lista

let numeros = [2, 8, 15, 23, 42, 7, 13];
let numeroProcurado = 23;
let encontrado = false;
let posicao = -1;

for (let i = 0; i < numeros.length; i++) {
    if (numeros[i] === numeroProcurado) {
        encontrado = true;
        posicao = i;
        break; // Encontrou, não precisa continuar procurando
    }
}

if (encontrado) {
    console.log(`Número ${numeroProcurado} encontrado na posição ${posicao}`);
} else {
    console.log(`Número ${numeroProcurado} não encontrado`);
}

Por que usar break aqui? Uma vez que encontramos o número, não há razão para continuar verificando o resto da lista. O break torna o código mais eficiente.

Exemplo: Primeiro Número Maior que um Valor

let numeros = [2, 8, 15, 23, 42, 7, 13];
let limite = 20;

console.log(`Procurando o primeiro número maior que ${limite}:`);

for (let i = 0; i < numeros.length; i++) {
    if (numeros[i] > limite) {
        console.log(`Encontrado: ${numeros[i]} na posição ${i}`);
        break;
    }
}

Saída:

Procurando o primeiro número maior que 20:
Encontrado: 23 na posição 3

Instrução continue - Pular para a Próxima Iteração

Ao contrário do break, que sai completamente do loop, o continue pula apenas a iteração atual e vai direto para a próxima. É como dizer "ignore este item e vá para o próximo".

Sintaxe

for (let i = 0; i < 10; i++) {
    if (i % 2 === 0) {
        continue; // Pula números pares
    }
    console.log(i);
}

Saída:

1
3
5
7
9

Os números pares (0, 2, 4, 6, 8) foram pulados - quando a condição i % 2 === 0 foi verdadeira, o continue fez o loop pular direto para a próxima iteração.

Exemplo Prático: Processando Apenas Elementos Válidos

let temperaturas = [20, -5, 30, 150, 25, -10, 35];
let tempMin = 0;
let tempMax = 50;

console.log(`Temperaturas válidas (entre ${tempMin}°C e ${tempMax}°C):`);

for (let i = 0; i < temperaturas.length; i++) {
    // Pula temperaturas fora do intervalo válido
    if (temperaturas[i] < tempMin || temperaturas[i] > tempMax) {
        continue;
    }
    
    console.log(temperaturas[i] + "°C");
}

Saída:

Temperaturas válidas (entre 0°C e 50°C):
20°C
30°C
25°C
35°C

As temperaturas -5, 150 e -10 foram ignoradas por estarem fora do intervalo válido.

Exemplo: Filtrando Dados ao Processar

let usuarios = [
    { nome: "Ana", idade: 25, ativo: true },
    { nome: "Bruno", idade: 17, ativo: true },
    { nome: "Carlos", idade: 30, ativo: false },
    { nome: "Diana", idade: 22, ativo: true }
];

console.log("Usuários ativos maiores de 18 anos:");

for (let i = 0; i < usuarios.length; i++) {
    // Pula usuários inativos
    if (!usuarios[i].ativo) {
        continue;
    }
    
    // Pula menores de idade
    if (usuarios[i].idade < 18) {
        continue;
    }
    
    console.log(`- ${usuarios[i].nome} (${usuarios[i].idade} anos)`);
}

Saída:

Usuários ativos maiores de 18 anos:
- Ana (25 anos)
- Diana (22 anos)

Quando Usar break vs continue

Use break quando:

  • Você encontrou o que procura e não precisa continuar
  • Uma condição de erro exige encerramento imediato
  • Você quer otimizar saindo do loop mais cedo

Use continue quando:

  • Quer pular elementos que não atendem critérios específicos
  • Precisa filtrar dados durante o processamento
  • Quer evitar aninhamento excessivo de if

Loops Aninhados - Loops Dentro de Loops

Loops podem conter outros loops dentro deles. Isso é chamado de aninhamento (nesting) e é extremamente útil para trabalhar com estruturas bidimensionais ou realizar operações complexas.

Conceito Básico

for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
        console.log(`i = ${i}, j = ${j}`);
    }
}

Saída:

i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 1, j = 0
i = 1, j = 1
i = 1, j = 2
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2

Como funciona:

  • O loop externo (i) executa uma vez
  • Para cada execução do loop externo, o loop interno (j) executa completamente
  • Quando o loop interno termina, o loop externo avança para a próxima iteração

Exemplo Prático: Tabuada Completa

console.log("=== TABUADA DO 1 AO 5 ===\n");

for (let i = 1; i <= 5; i++) {
    console.log(`Tabuada do ${i}:`);
    
    for (let j = 1; j <= 10; j++) {
        console.log(`${i} x ${j} = ${i * j}`);
    }
    
    console.log(""); // Linha em branco entre tabuadas
}

Exemplo: Matriz de Números

let linhas = 4;
let colunas = 5;

for (let i = 0; i < linhas; i++) {
    let linha = "";
    
    for (let j = 0; j < colunas; j++) {
        let numero = (i * colunas) + j + 1;
        linha += numero.toString().padStart(3, " ") + " ";
    }
    
    console.log(linha);
}

Saída:

  1   2   3   4   5 
  6   7   8   9  10 
 11  12  13  14  15 
 16  17  18  19  20

Qual Loop Escolher?

Para muitos problemas, os loops for, while e do...while são amplamente intercambiáveis. Todos podem resolver os mesmos problemas - a escolha depende principalmente do contexto e da clareza do código.

Princípio da Escolha

Cada tipo de loop é otimizado para diferentes padrões de controle de iteração. Escolher o loop certo torna seu código mais legível e expressa melhor sua intenção.

Diretrizes Práticas

Use for quando:

  • ✓ Você souber o número exato de iterações
  • ✓ Trabalhar com índices de arrays
  • ✓ Precisar de um contador explícito
// Processar todos os elementos de um array
for (let i = 0; i < array.length; i++) {
    ++array[i]
}

Use while quando:

  • ✓ A condição de parada for mais complexa
  • ✓ O número de iterações depender de algo que acontece durante a execução
  • ✓ A lógica for mais clara expressando "enquanto isso for verdade"
// Continuar até o jogador decidir sair
while (jogadorQuerContinuar && vidasRestantes > 0) {
    // Código
}

Use do...while quando:

  • ✓ Precisar executar o código pelo menos uma vez
  • ✓ Coletar entrada do usuário antes de validar
  • ✓ Garantir uma primeira execução independente
// Mostrar menu e pedir opção pelo menos uma vez
do {
    // Código para mostrar menu e obter opção
} while (opcao !== "sair");

Exemplo de Intercambiabilidade

O mesmo problema resolvido com diferentes loops:

// Problema: Somar números de 1 a 10

// Solução 1: for
let soma1 = 0;
for (let i = 1; i <= 10; i++) {
    soma1 += i;
}

// Solução 2: while
let soma2 = 0;
let i = 1;
while (i <= 10) {
    soma2 += i;
    i++;
}

// Solução 3: do...while
let soma3 = 0;
let j = 1;
do {
    soma3 += j;
    j++;
} while (j <= 10);

// Todas as soluções produzem: 55

Neste caso, o for é provavelmente a escolha mais clara porque expressa diretamente a intenção: "repetir 10 vezes".

Boas Práticas com Loops

1. Sempre Evite Loops Infinitos

Problema:

// ❌ INCORRETO - Loop infinito
for (let i = 0; i < 10; /* esqueceu i++ */) {
    console.log(i);
}

Solução:

// ✅ CORRETO
for (let i = 0; i < 10; i++) {
    console.log(i);
}

Por quê? Loops infinitos podem travar completamente seu programa ao nunca satisfazer a condição de parada. Sempre certifique-se de que a condição eventualmente se tornará falsa.

2. Use Nomes Descritivos para Variáveis de Controle

Ruim:

// ❌ Nomes genéricos não comunicam intenção
for (let i = 0; i < estudantes.length; i++) {
    console.log(estudantes[i]);
}

Melhor:

// ✅ Nomes descritivos melhoram legibilidade
for (let indiceEstudante = 0; indiceEstudante < estudantes.length; indiceEstudante++) {
    console.log(estudantes[indiceEstudante]);
}

Por quê? Nomes descritivos melhoram legibilidade e manutenibilidade do código. Quando você ou outra pessoa ler o código meses depois, ficará claro o que cada variável representa.

Exceção: Em loops simples e curtos, i, j, k são aceitáveis por convenção:

// ✅ OK para loops simples
for (let i = 0; i < 10; i++) {
    console.log(i);
}

4. Otimize Cálculos Repetitivos

Menos Eficiente:

// ❌ array.length é calculado a cada iteração
for (let i = 0; i < array.length; i++) {
    ++array[i]
}

Mais Eficiente:

// ✅ tamanho é calculado apenas uma vez
let tamanho = array.length;
for (let i = 0; i < tamanho; i++) {
    ++array[i]
}

Por quê? O princípio que orienta a otimização de performance em loops é minimizar cálculos repetitivos desnecessários dentro do loop. Embora JavaScript moderno otimize muitos casos automaticamente, é boa prática evitar trabalho redundante.

5. Use break e continue com Moderação

// Bom uso de continue - filtragem clara
for (let i = 0; i < usuarios.length; i++) {
    if (!usuarios[i].ativo) continue;
    ++usuarios[i];
}

// Uso excessivo pode prejudicar legibilidade
// Se você tem muitos continue/break, considere refatorar

Aplicações Práticas no Mundo Real

Vamos ver como loops são usados em situações reais de programação.

Aplicação 1: Sistema de Notas

let notas = [7.5, 8.0, 6.5, 9.0, 7.0];
let soma = 0;
let maiorNota = notas[0];
let menorNota = notas[0];

// Calcular média e encontrar maior/menor nota
for (let i = 0; i < notas.length; i++) {
    soma += notas[i];
    
    if (notas[i] > maiorNota) {
        maiorNota = notas[i];
    }
    
    if (notas[i] < menorNota) {
        menorNota = notas[i];
    }
}

let media = soma / notas.length;

console.log("=== ANÁLISE DE NOTAS ===");
console.log(`Média: ${media.toFixed(2)}`);
console.log(`Maior nota: ${maiorNota}`);
console.log(`Menor nota: ${menorNota}`);
console.log(`Status: ${media >= 7 ? "APROVADO" : "REPROVADO"}`);

Aplicação 3: Gerador de Relatórios

let vendas = [
    { produto: "Notebook", valor: 3500, quantidade: 2 },
    { produto: "Mouse", valor: 50, quantidade: 10 },
    { produto: "Teclado", valor: 150, quantidade: 5 },
    { produto: "Monitor", valor: 800, quantidade: 3 }
];

console.log("=== RELATÓRIO DE VENDAS ===\n");
console.log("PRODUTO".padEnd(15) + "QTD".padEnd(8) + "VALOR UNIT.".padEnd(15) + "TOTAL");
console.log("-".repeat(50));

let totalGeral = 0;

for (let i = 0; i < vendas.length; i++) {
    let venda = vendas[i];
    let totalItem = venda.valor * venda.quantidade;
    totalGeral += totalItem;
    
    console.log(
        venda.produto.padEnd(15) + 
        venda.quantidade.toString().padEnd(8) + 
        `R$ ${venda.valor.toFixed(2)}`.padEnd(15) + 
        `R$ ${totalItem.toFixed(2)}`
    );
}

console.log("-".repeat(50));
console.log(`TOTAL GERAL: R$ ${totalGeral.toFixed(2)}`);

Aplicação 4: Processamento de Estoque

let estoque = [
    { codigo: 101, nome: "Produto A", quantidade: 5, minimo: 10 },
    { codigo: 102, nome: "Produto B", quantidade: 15, minimo: 10 },
    { codigo: 103, nome: "Produto C", quantidade: 3, minimo: 5 },
    { codigo: 104, nome: "Produto D", quantidade: 20, minimo: 15 }
];

console.log("=== ALERTA DE ESTOQUE BAIXO ===\n");

let produtosBaixos = 0;

for (let i = 0; i < estoque.length; i++) {
    if (estoque[i].quantidade < estoque[i].minimo) {
        produtosBaixos++;
        let diferenca = estoque[i].minimo - estoque[i].quantidade;
        
        console.log(`⚠️  ${estoque[i].nome} (Cód: ${estoque[i].codigo})`);
        console.log(`   Quantidade atual: ${estoque[i].quantidade}`);
        console.log(`   Quantidade mínima: ${estoque[i].minimo}`);
        console.log(`   Necessário repor: ${diferenca} unidades\n`);
    }
}

if (produtosBaixos === 0) {
    console.log("✓ Todos os produtos estão com estoque adequado!");
} else {
    console.log(`Total de produtos com estoque baixo: ${produtosBaixos}`);
}

Armadilhas Comuns e Como Evitá-las

Armadilha 1: Modificar o Contador Incorretamente

// ❌ ERRADO - Pula números
for (let i = 0; i < 10; i += 2) {
    console.log(i);
    // Saída: 0, 2, 4, 6, 8 (pulou os ímpares)
}

// ✅ CORRETO - Para todos os números
for (let i = 0; i < 10; i++) {
    console.log(i);
}

Armadilha 2: Condição Que Nunca É Satisfeita

// ❌ ERRADO - Loop infinito
let i = 10;
while (i < 5) {
    console.log(i);
    i++; // i nunca será menor que 5
}

// ✅ CORRETO
let i = 0;
while (i < 5) {
    console.log(i);
    i++;
}

Armadilha 3: Acessar Índices Fora do Array

let numeros = [10, 20, 30];

// ❌ ERRADO - Tenta acessar índice que não existe
for (let i = 0; i <= numeros.length; i++) {
    console.log(numeros[i]); // numeros[3] é undefined
}

// ✅ CORRETO - Para antes do limite
for (let i = 0; i < numeros.length; i++) {
    console.log(numeros[i]);
}

Armadilha 4: Modificar Array Durante Iteração

let numeros = [1, 2, 3, 4, 5];

// ❌ PERIGOSO - Modificar array durante iteração
for (let i = 0; i < numeros.length; i++) {
    if (numeros[i] % 2 === 0) {
        numeros.splice(i, 1); // Remove elemento
        // Isso desloca todos os elementos seguintes!
    }
}

// ✅ MELHOR - Iterar de trás para frente
for (let i = numeros.length - 1; i >= 0; i--) {
    if (numeros[i] % 2 === 0) {
        numeros.splice(i, 1);
    }
}

// ✅ AINDA MELHOR - Criar novo array
let impares = [];
for (let i = 0; i < numeros.length; i++) {
    if (numeros[i] % 2 !== 0) {
        impares.push(numeros[i]);
    }
}

As estruturas de repetição são ferramentas essenciais no arsenal de qualquer programador. Elas transformam tarefas que seriam impraticáveis manualmente em operações simples e eficientes.

Próximos Passos

Na próxima aula aprenderemos a criar nossas próprias funções. Você aprenderá:

  • A sitaxe da criação de funções
  • Como passar e retornar valores
  • O que é e como funciona o escopo
  • Boas práticas da criação de funções

Continue sua jornada de aprendizado e lembre-se: cada loop que você escreve está aprimorando suas habilidades de pensamento lógico e resolução de problemas! 🚀