JavaScript Loops: while e for
Tags: javascript, tutorial, programming
Published: 2022-12-29 18:15:02

Muitas vezes precisamos repetir ações. Por exemplo, enviar produtos de uma lista um após o outro ou apenas executar o mesmo código para cada número de 1 a 10. Loops são uma maneira de repetir o código várias vezes.

## O loop While

O loop `while` tem a seguinte sintaxe:

```jsx
while (condition) {
  // code
  // o chamado corpo de loop
}
```

Enquanto a condição for true, o código do corpo do loop é executado. Por exemplo, o loop abaixo gera `i` **quando** `i < 3`:

```jsx
let i = 0
while (i < 3) {
  alert(i)
  i++
}
```

Uma única execução do corpo do loop, é chamada de iteração. O loop no exemplo acima, faz três iterações. Se `i++` estivesse faltando no exemplo acima, o loop se repetiria (em teoria) para sempre. Na prática, o navegador fornece maneiras de interromper esses loops e, no JavaScript do lado do servidor, podemos eliminar o processo.

Qualquer expressão ou variável pode ser uma condição de loop, não apenas comparações: a condição é avaliada e convertida em booleana por `while`.

Por exemplo, uma maneira mais curta de escrever `while(i != 0)` é `while(i)`:

```jsx
let i = 3;
while (i) { // quando i se torna 0, a condição se torna false e o loop para
  alert( i );
  i--;
}
```
### Chaves não são necessárias para um corpo de linha única

Se o corpo do loop tiver uma única instrução, podemos imitir as chaves `{...}`:

```jsx
let i = 3;
while (i) alert(i--);
```

## O loop "do..while"

A verificação de condição pode ser movida abaixo do corpo do loop, usando a sintaxe `do...while`:

```jsx
do {
  // loop body
} while (condition);
```
O loop primeiro executará o corpo, depois verificará a condição e, embora seja true, execute-o novamente e novamente. Por exemplo:

```jsx
let i = 0

do {
  alert( i );
  i++;
} while (i < 3);
```
Essa forma de sintaxe só deve ser usada, quando você deseja que o corpo do loop seja executado pelo menos uma vez. Independentremente se a condição for true, normalmente a outra forma é preferida: `while()...`

## O loop "for"

O loop `for` é mais complexo, mas é o mais utilizado. 

Se parece com isso:

```jsx
for (begin; condition; step) {
  // ... loop body ...
}
```
Vamos aprender o significado dessas partes. O loop abaixo executa a função `alert(i)` de `i` até `0` (mas não incluindo) `3`:

```jsx
for (let i = 0; i < 3; i++) {
  alert(i)
}
```
Vamos examinar a declaração `for` parte por parte: 

| Início | Código | Descrição
| --- | ----------- | ---- |
| começo | let i = 0 | Executa uma vez ao entrar no loop. |
| condição | i < 3 | Verificado antes de cada iteração do loop. Se falso, o loop para. |
| corpo | alert(i) | Executa repetidamente enquanto a função for true.|
| passo | i ++ | Executa após o corpo em cada iteração. |

O algoritmo do loop geralmente funciona assim:

```jsx
Run begin
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ (if condition → run body and run step)
→ ...
```
Ou seja, o começo executa uma vez, em seguida, itera: após cada teste de condição, o corpo e o próximo passo são executados. Se você é novo em loops, pode ser útil voltar ao exemplo e reproduzir como ele é executado passo a passo em um pedação de papel.

Aqui está exatamente o que acontece no nosso caso:

```jsx
// for (let i = 0; i < 3; i++) alert(i)

// run begin
let i = 0
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// if condition → run body and run step
if (i < 3) { alert(i); i++ }
// ...finish, because now i == 3
```
### Pular partes

Qualquer parte `for` pode ser ignorada. Por exemplo, podemos omitir o começo se não precisarmos fazer nada no início do loop.

Como aqui:

```jsx
let i = 0; // nós já declaramos e atribuímos

for (; i < 3; i++) { // não há necessidade de "começar"
  alert( i ); // 0, 1, 2
}
```
Também podemos remover o papel de step:

```jsx
let i = 0;

for (; i < 3;) {
  alert( i++ );
}
```
### Quebrando o ciclo

Normalmente, um loop termina quando sua condição se torna false. Mas podemos forçar a saída a qualquer momento usando a diretiva especial `break`.

Por exemplo, o loop abaixo pede ao usuário uma série de números, "quebrando" quando nenhum número é digitado:

```jsx
let sum = 0;

while (true) {

  let value = +prompt("Digite um número", '');

  if (!value) break; // (*)

  sum += value;

}
alert( 'Sum: ' + sum );
```
A diretiva `break` é ativada na linha `(*)` se o usuário inserir uma linha vazia ou cancelar a entrada. Ele interrompe o loop imediatamente, passando o controle para a primeira linha após o loop. Ou seja, `alert()`.

A combinação de "loop infinito" + `break` conforme necessário", é ótima para situações em que a condição de um loop deve ser verificada não no início ou no final do loop, mas no meio ou mesmo em vários locais do seu corpo.

## Continue para a próxima iteração

A diretiva `continue` é uma "versão mais leve" do `break`. Não para todo o loop. Em vez disso, ele interrompe a iteração atual e força o loop a iniciar um novo (se a condição permitir).

Podemos usá-lo se terminarmos a iteração atual e quisermos passar para a próxima. O loop abaixo usa `continue` para produzir apenas valores ímpares:

```jsx
for (let i = 0; i < 10; i++) {

  // se true, pule a parte restante do corpo
  if (i % 2 == 0) continue;

  alert(i); // 1, then 3, 5, 7, 9
}
```
Para valores pares de `i`, a diretiva `continue` interrompe a execução do corpo e passa o controle para a próxima iteração de for(com o próximo número). Portanto, o alert é chamado apenas para valores ímpares.

### A diretiva continue ajuda a diminuir o aninhamento

Um loop que mostra valores ímpares pode ser assim:

```jsx
for (let i = 0; i < 10; i++) {

  if (i % 2) {
    alert( i );
  }

}
```
Do ponto de vista técnico, isso é idêntico ao exemplo acima. Certamente, podemos apenas agrupar o código em um bloco `if` em vez de usar `continue`.

Mas, como efeito colateral, isso criou mais um nível de aninhamento (a chamada alert dentro das chaves). Se o código dentro de `if` for maior que algumas linhas, isso pode diminuir a legibilidade geral.

## Rótulos para interromper/continuar

Às vezes, precisamos sair de vários loops aninhados de uma só vez. Por exemplo, no código abaixo, passamos por cima de ie j, solicitando as coordenadas (i, j)de (0,0)a (2,2): 

```jsx
for (let i = 0; i < 3; i++) {

  for (let j = 0; j < 3; j++) {

    let input = prompt(`Value at coords (${i},${j})`, '');

    //  se quisermos sair daqui para Done (abaixo)?
  }
}

alert('Done!');
```
Precisamos de uma maneira de interromper o processo se o usuário cancelar a entrada. O break depois do input, apenas quebraria o loop interno. Isso não é suficiente – rótulos, venham ao resgate!

Um rótulo é um identificador com dois pontos antes de um loop:

```jsx
labelName: for (...) {
  ...
}
```

A instrução `break <labelName>` abaixo quebra o rótulo:

```jsx
outer: for (let i = 0; i < 3; i++) {

  for (let j = 0; j < 3; j++) {

    let input = prompt(`Valor em coordenadas (${i},${j})`, '');

    // se for uma string vazia ou cancelada, saia de ambos os loops
    if (!input) break outer; // (*)

    // do something with the value...
  }
}

alert('Done!')
```
No código acima, `break outer` significa procurar o rótulo nomeado `outer` e sair desse loop. Então o controle vai dereto de `(*)` para `alert('Done!')`.

```jsx
outer:
for (let i = 0; i < 3; i++) { ... }
```