Laços de repetição em Javascript
Tags: braziliandevs, javascript
Published: 2021-03-23 00:44:05

Laços (loops) de repetição são estruturas essênciais em praticamente todo algoritmo, e ter um bom domínio dessas estruturas é obrigatório para qualquer pessoa programadora. 

Ultimamente, nos meus estudos de Javascript, descobri que esta linguagem não possui somente os laços de repetição comuns. Isso quer dizer que `for`,`while` e `do-while` não são a única maneira de iterar sobre estruturas iteráveis e realizar repetições. E como já venho fazendo, se eu encontro algo interessante, resolvo escrever sobre. 

Então, hoje vamos falar um pouco sobre os cinco tipos básicos de laços de repetição e sobre um método de objetos iteráveis que eu achei muito interessante. Vamos nessa!

## For
Se você programa com certeza já conhece o laço for. Sua estrutura padrão é: 
```javascript
for(INICIALIZAÇÃO;CONDIÇÃO_DE_CONTINUIDADE;ALTERAÇÃO_DA_VARIAVEL_DE_CONTROLE){
    codigo
}
```
Este tipo de laço geralmente é usado quando você quer uma quantidade finita e conhecida de repetições, embora ele também possa atuar como laço infinito se você mantiver a condição de continuidade ou a alteração de variável em branco.

Para usar esse laço, você precisa de uma variável para armazenar um valor que será testado a cada iteração do loop pela condição de continuidade. Essa variável pode ser delcarada dentro ou fora da inicialização do loop, porém é obrigatório que na inicialização do loop um valor seja atribuido a essa variável.

A condição de contuidade é geralmente uma condição relacional elaborada com a variável de controle, e enquanto esta condição for verdadeira, a variável é alterada de acordo com a especificação do usuário e o laço continua suas iterações. No momento em que esta condição é falsa, se sai do laço.

Por fim temos a parte da alteração da variável de controle, que pode ser tanto um incremento quanto um decremento a parte de incremento nada mais é do que a alteração da variável de controle.

## While 
O laço while também não é uma surpresa para pessoas que já possuem algum conhecimento de programação em outra linguagem. Sua estrutura padrão é:
```javascript
while(CONDIÇÃO_DE_CONTINUIDADE){
    codigo
}
```
Este tipo de laço geralmente é usado quando você não sabe a quantidade total de repetições que precisará iterar o código. É  usual que a estrutura `while` seja usada para ler um input do usuário, por exemplo, e continuar repetindo enquanto um valor determinado (como "x" para fechar a aplicação), não seja lido. 

Esta estrutura também funciona com uma variável de controle que precisa ser criada fora do escopo do loop e incrementada dentro do escopo do mesmo, sendo que a condição de continuidade está também relacionada a esta variável de controle.

Vale lembrar também que é comum dizer que o laço `while` possui de 0 a infinitas repetições, porque a condição de continuidade é sempre testada antes da execução do código, e se supormos que ela já não é atendida na primeira execução, o laço é terminado antes mesmo de executar o código.

## Do-while 
O laço `do-while` também está presente em quase todas as linguagens de programação. Sua estrutura padrão é:
```javascript
do{
    codigo
}while(CONDIÇÃO_DE_CONTINUIDADE);
```
Este tipo de laço também é usado quando você não sabe a quantidade total de repetições que precisará iterar o código, e assim como no `while` e no `for`, a condição de continuidade deve estar relacionada a uma variável de controle. Esta variável deve ser declarada fora do escopo da estrutura e incrementada dentro do escopo. 

Vale lembrar também que é comum dizer que o laço `do-while` possui de 1 a infinitas repetições, porque a condição de continuidade é sempre testada ao final da execução do código, o que faz com que o código sempre seja executado ao menos uma vez, mesmo que a condição de continuidade seja falsa antes da entrada no loop. 

## For..in
Agora começamos a parte divertida que são as estruturas "extras" do Javascript. O `for..in` é uma estrutura de repetição especial para a iteração de objetos. Ela itera sobre as propriedades(atributos) de um objeto, na ordem em que se apresentam no código, e sua estrutura básica é:
``` javascript
for(ATRIBUTO in OBJETO){
    codigo
}
```
`Atributo`, neste caso, é uma variável que pode ser declarada dentro da chamada do laço ou fora, e `objeto` é o objeto sobre o qual queremos iterar.  A utilização deste laço é bem simples, contanto que nos lembremos que um objeto é composto por vários membros, e que cada membro possui um nome e um valor.

Quando o laço começa, a variável `atributo` recebe o nome do primeiro membro encontrado dentro do objeto, na próxima iteração, o conteúdo da variável `atributo` é atualizado para o nome do segundo membro do objeto, e assim por diante enquanto houverem membros no objeto.

Para acessar os valores dos membros do objeto, é possível usar a notação de chaves, de modo que um código como o apresentado abaixo pode ser usado para imprimir todos os nomes e seus valores. 

```javascript
for(let att in obj){
    console.log(`O membro ${att} tem valor ${obj[att]}`);
}
```

É importante salientar que embora esta estrutura possa iterar sobre arrays, esta pratica não é recomendada. Para este tipo de estruturas de dados, existe uma estrutura muito similar, o `for..of` que veremos em seguida.

## For..of
Se você entendeu como o `for..in` funciona, a estrutura `for..of` é bastante similar, porém ao invés de objetos, ela itera sobre objetos iterativos (arrays, sets, mapas, entre outros).
``` javascript
for(VALOR of ITERÁVEL){
    codigo
}
```
`valor`, neste caso, é uma variável que pode ser declarada dentro da chamada do laço ou fora, e `iterável` é o objeto iterável (array, set ou mapa) sobre o qual queremos iterar. 

Quando o laço começa, a variável `valor` recebe o valor do primeiro elemento do objeto iterável, na próxima iteração, o conteúdo da variável `valor` é atualizado para o valor do segundo elemento do objeto iterável, e assim por diante enquanto houverem elementos no objeto iterável.

E só para garantir que você sabe quais são os elementos dos objetos iteráveis:

- Vetores: um único número/caracter/string ou qualquer outra coisa que ocupe uma posição do vetor
- Sets: um único número/caracter/string ou qualquer outra coisa que ocupe uma posição do set
- Mapas: único par [chave, valor]

Com este laço, por exemplo, não precisamos conhecer a quantidade de elementos de um vetor para imprimí-lo.

``` javascript
for(let valor of vetor){
    console.log(valor);
}
```

Apesar de este tipo de laço ser mais simples para imprimir o conteúdo de um objeto iterável, é importante lembrar que esta estrutura de repetição não guarda nenhum registro de qual posição do objeto iterável determinado valor ocupa, portanto é importante usá-lo com sabedoria.


## forEach()
E para finalizar o artigo de hoje, trago a estrutura de repetição que mais me chamou a atenção do Javascript, o método `forEach()` existente tanto na classe `Array` quando na classe `Map`. Esse método executa uma função em cada elemento do array ou do mapa. Vejamos com alguns exemplos como estes métodos funcionam.
### Array.forEach()
Primeiro, vamor criar um array simples, e imaginar uma função que queremos que atue sobre cada um dos elementos.
```javascript
const vetor = [-3,-2,-1,0,1,2,3,4];

function imprimeDobroPositivo(num){
    if (num < 0){
        num = Math.abs(num);
    }
    num *= 2;
    console.log(num);
}
```

Bom, temos um vetor com números positivos e negativos, e uma função que vai transformar os números negativos em positivos, duplicar este valor e imprimir o valor duplicado. 

Agora, vamos ao `forEach()`. Primeiro, temos que saber que ela é um método da classe array, então será chamada no estilo `vetor.forEach()`. Em segundo lugar, precisamos entender qual parâmetro passar para esta função. Nada mais do que a função que criamos anteriormente, mas sem os parênteses. 

```javascript
vetor.forEach(imprimeDobroPositivo);
```

A nossa *callback function*, a função que vamos chamar dentro do `forEach()` pode ter até três parâmetros, sendo que pelo menos um deles (o elemento atual) é obrigatório. Este parâmetro não é especificado na chamada da função, mas sim na sua declaração. Na delcaração da função `imprimeDobroPositivo`, temos um único parâmetro, que por padrão será associado ao elemento referente a iteração. Por isso, o código acima funciona.

Agora vamos falar sobre os outros dois parâmetros. Como precisamos alterar estes parâmetros na função de callback (no nosso caso `imprimeDobroPositivo`), bastaria adicionar mais dois parâmetros. Por padrão, o segundo parâmetro será o índice do elemento, e o terceiro o próprio array. Vamor criar um novo exemplo então:

```Javascript
vetor = [1,2,3]

function imprimeBonito(numero,i,arr){
//quando esta função for chamada, numero (primeiro parâmetro) fará
//referência ao elemento da iteração, i (segundo parâmetro) fará
//referência ao índice do elemento e arr (terceiro parâmetro) é o 
//próprio array.
console.log(`${numero} é o elemento na posição ${i} do vetor ${arr}`);
}

vetor.forEach(imprimeBonito);
```

O resultado deste trecho de código nada mais é do que:
```
1 é o elemento na posição 0 do vetor 1,2,3
2 é o elemento na posição 1 do vetor 1,2,3
3 é o elemento na posição 2 do vetor 1,2,3
```

Este tipo de iteração pode até não parecer grande coisa com os exemplos simples que utilizamos, mas se você precisar realizar grandes manipulações em elementos de arrays, com certeza o `forEach()` pode ser muito útil para você.

### Map.forEach()
Se você entendeu como o `Array.forEach()` funciona, com certeza não vai ter problemas com este método. Assim como método anterior, este método é chamado no estilo `map.forEach(função)`, e esta função também deve ter um parâmetro obrigatório (o valor do item da iteração), e pode ter como parâmetros opcionais a chave do elemento e o objeto map que está sendo iterado. Vamos criar um exemplo rápido com um mapa que armazenas pessoas e um id para essas pessoas.
```javascript
pessoas = new Map ([[1,"Maria"],[2, "Antônio"],[3, "Angélica"]]);
function escreveNomeID(id, nome){
  console.log(`${id} tem o id ${nome}`);
}

pessoas.forEach(escreveNomeID);
```
Confesso que não tenho muita experiencia com mapas, então não consigo imaginar um exemplo realmete útil com a utilização desta estrutura de dados, porém vocês podem comentar neste post algum exemplo que achem interessante.

E com isso, eu finalizo este artigo sobre estruturas (e métodos) de repetição em Javascript. Espero que este conteúdo possa ter sido útil para alguma coisa, e até a próxima.