Laços em JavaScript
Laços (Loops) permitem executar uma ação repetidamente, dependendo de certas condições. Em JavaScript, existem os seguintes tipos de laços:
- for
- for...in
- for...of
- while
- do...while
Laço for
O laço for
tem a seguinte definição formal:
for ([inicialização do contador]; [condição]; [incremento do contador]) {
// ações
}
Por exemplo, usamos o laço for
para iterar números de 0 a 4:
for (let i = 0; i < 5; i++) {
console.log(i);
}
console.log("Fim da execução");
A primeira parte da declaração do laço let i = 0
cria e inicializa o contador, a variável i
. Antes da execução do laço, seu valor será 0. Isso é equivalente à declaração de uma variável.
A segunda parte é a condição para a execução do laço: i < 5
. Neste caso, o laço será executado enquanto o valor de i
não atingir 5.
A terceira parte i++
é o incremento do contador por uma unidade.
Portanto, na inicialização, a variável i
é 0. Este valor satisfaz a condição i < 5
, então o bloco de código dentro do laço é executado, especificamente a linha:
console.log(i);
Após a execução do bloco de código, a terceira parte da declaração do laço é executada, incrementando o contador. Assim, a variável i
torna-se 1. Este valor também satisfaz a condição, então o bloco de código é executado novamente. Deste modo, o bloco será executado 5 vezes, até que o valor de i
se torne 5. Este valor NÃO satisfaz a condição, resultando na saída do laço. O controle do programa então passa para as instruções após o bloco do laço. A saída no console será:
0 1 2 3 4 Fim da execução
Cada repetição do laço é chamada de iteração. Assim, neste caso, haverá 5 iterações.
Você pode aumentar o contador de formas diferentes, como decrementando por uma unidade:
for (let i = 10; i > 5; i--) {
console.log(i);
}
Neste caso, os números de 10 a 6 são exibidos no console.
Ou incrementar o contador por 2:
for (let i = 0; i < 10; i += 2) {
console.log(i);
}
Aqui, todos os números pares de 0 a 8 são exibidos no console.
É possível omitir diferentes partes da declaração do laço:
let i = 0;
for (; i < 60; ) {
console.log(i);
i = i + 10;
}
Neste caso, a variável i
é definida fora do laço. A própria declaração do laço contém apenas a condição; as outras duas partes estão ausentes. A modificação da variável ocorre dentro do bloco do laço, onde ela é incrementada em 10. Isso resulta na exibição dos números 0, 10, 20, 30, 40, 50 no console.
O contador é útil como índice de elementos de um array, permitindo iterar sobre o array:
const people = ["Tom", "Sam", "Bob"];
for (let i = 0; i < 3; i++) {
console.log(people[i]);
}
Saída no console do navegador:
Tom Sam Bob
Uso de Múltiplos Contadores em um Laço
Quando necessário, você pode usar vários contadores:
for (let i = 1, j = 1; i < 5, j < 4; i++, j++) {
console.log(i + j);
}
// 1ª iteração: i=1, j=1; i + j = 2
// 2ª iteração: i=2, j=2; i + j = 4
// 3ª iteração: i=3, j=3; i + j = 6
Aqui são usados dois contadores e duas condições. Vamos considerar passo a passo o que acontece:
Primeira iteração. Valores iniciais das variáveis
i
ej
:i = 1, j = 1;
Cada variável tem suas próprias condições. No início, os valores das variáveis atendem a essas condições:
i < 5, j < 4;
No bloco do laço, a soma dessas variáveis é exibida. Em seguida, os valores de ambas as variáveis são incrementados em uma unidade. Eles se tornam:
i = 2), j = 2);
Esses valores também atendem às condições, portanto, a segunda iteração é executada.
Segunda iteração. Valores das variáveis
i
ej
:i = 2, j = 2;
Após a execução do bloco do laço, os valores de ambas as variáveis são incrementados em uma unidade. Eles se tornam:
i = 3, j = 3;
Esses valores também atendem às condições, portanto, a terceira iteração é executada.
Terceira iteração. Valores das variáveis
i
ej
: Após a execução do bloco do laço, os valores de ambas as variáveis são incrementados em uma unidade. Eles se tornam:i = 4, j = 4;
O valor da variável
i
ainda atende à condiçãoi < 5
, mas o valor da variávelj
(4) NÃO atende à condiçãoj < 4
. Portanto, ocorre a saída do laço. O laço é concluído.
Execução de Ações na Declaração do Laço
Vale destacar que a terceira parte do laço, onde geralmente ocorre a alteração do contador, na realidade representa uma ação arbitrária que é executada após a conclusão do laço. Assim, podemos escrever da seguinte maneira:
for (let i = 0; i < 5; console.log(i++));
console.log("Fim da execução");
Aqui não é definido um bloco de laço, e as próprias ações do laço são definidas na terceira parte do cabeçalho do laço console.log(i++)
.
A saída no console será:
0 1 2 3 4 Fim da execução
Similarmente, na primeira parte da definição do laço - a inicialização - podemos realizar algumas ações, não necessariamente apenas a declaração do contador:
let i = 0;
for (console.log("Init"); i < 5; i++) {
console.log(i);
}
A definição do contador é colocada fora do laço, e na parte de inicialização do laço, uma string é exibida no console. Saída no navegador:
Init 0 1 2 3 4
Laços Aninhados
Um laço pode conter outro laço dentro de si:
for (let i = 1; i <= 5; i++) {
for (let j = 1; j <= 5; j++) {
console.log(i * j);
}
}
Aqui, um laço está embutido dentro de outro. No laço externo, a variável i
é inicializada. Inicialmente, ela é igual a 1, o que satisfaz a condição do laço (i <= 5)
, então o bloco de código do laço, que contém o laço interno, é executado.
No laço interno, a variável-contador ``é inicialmente igual a 1, e então o laço interno executa 5 iterações, até que a variávelj
se torne igual a 5.
Depois que o bloco do laço externo é concluído, a variável i
é incrementada em 1 e se torna igual a 2, o que novamente atende à condição. O bloco do laço externo é então executado novamente. Neste bloco, o laço interno é executado mais cinco vezes. E assim por diante. No final, o laço interno será executado 25 vezes.
Usando laços aninhados e múltiplos contadores, é possível iterar sobre arrays multidimensionais:
const people = [
["Tom", 39],
["Sam", 28],
["Bob", 42],
];
for (let i = 0; i < 3; i++) {
// iterando sobre o array bidimensional
for (let j = 0; j < 2; j++) {
// iterando sobre os arrays aninhados
console.log(people[i][j]);
}
console.log("================="); // para separar os elementos
}
Aqui, o array people
representa um array bidimensional de 3 elementos, onde cada elemento é, por sua vez, um subarray de 2 elementos — nominalmente, nome e idade do usuário. No laço externo, definimos o contador i
para passar por todos os subarrays no array bidimensional people
, e no laço interno, definimos o contador j
para passar por todos os elementos de cada subarray. Saída no console:
Tom 39 ================= Sam 28 ================= Bob 42 =================
Laço while
O laço while é executado enquanto uma determinada condição for verdadeira. Sua definição formal é:
while (condição) {
// ações
}
Vamos novamente exibir com o while
os números de 1 até 5:
let i = 1;
while (i <= 5) {
console.log(i);
i++;
}
O laço while
aqui será executado enquanto o valor de i
não se tornar igual a 6.
do..while
No laço do..while
, o código do laço é executado primeiro, e depois a condição é verificada na instrução while
. Enquanto essa condição for verdadeira, o laço se repete. Por exemplo:
let i = 1;
do {
console.log(i);
i++;
} while (i <= 5);
Aqui, o código do laço será executado 5 vezes, até que i
se torne igual a 5. O laço do
garante que as ações sejam executadas pelo menos uma vez, mesmo se a condição na instrução while
não for verdadeira inicialmente.
Operadores continue e break
Às vezes é necessário sair de um laço antes de sua conclusão. Nesse caso, podemos usar o operador break
:
for (let i = 1; i <= 6; i++) {
if (i === 4) break;
console.log(i);
}
console.log("Fim da execução");
Este laço incrementa a variável i
de 1 até 6 inclusive, de acordo com a condição do laço, o bloco do laço deveria ser executado 6 vezes, produzindo 6 iterações. No entanto, como o bloco do laço verifica se if(i === 4) break;
, quando o valor da variável i
atinge 4, essa condição interrompe a execução do laço usando o operador break
. E o laço termina.
1 2 3 Fim da execução
Se precisarmos apenas pular uma iteração, mas não sair do laço, podemos usar o operador continue
. Por exemplo, vamos modificar o exemplo anterior, mas em vez de break
, usaremos continue
:
for (let i = 1; i <= 6; i++) {
if (i === 4) continue;
console.log(i);
}
console.log("Fim da execução");
Neste caso, quando o valor da variável i
se tornar 4, a expressão i === 4
retornará true
, então a construção if (i === 4) continue;
será executada. Com o operador continue
, ela termina a iteração atual, as instruções subsequentes do laço não serão executadas, e o laço avançará para a próxima iteração:
1 2 3 5 6 Fim da execução
for..in
O laço for..in
é principalmente usado para iterar sobre objetos. Sua definição formal é:
for (propriedade in objeto) {
// ações
}
Este laço percorre todas as propriedades de um objeto. Por exemplo:
const person = { name: "Tom", age: 37 };
for (prop in person) {
console.log(prop);
}
Aqui, o objeto person
, que possui duas propriedades - name
e age
- é iterado. Consequentemente, veremos no console:
name age
Obtendo as propriedades e usando a sintaxe especial objeto[propriedade]
, podemos obter o valor de cada propriedade:
const person = { name: "Tom", age: 37 };
for (prop in person) {
console.log(prop, person[prop]);
}
Saída no console:
name Tom age 37
for..of
O laço for...of
é destinado à iteração sobre coleções de dados. Por exemplo, uma string é essencialmente uma coleção de caracteres. E podemos iterá-la usando este laço:
const text = "Hello";
for (char of text) {
console.log(char);
}
Consequentemente, o laço itera todos os caracteres da string text
e coloca cada caractere corrente na variável char
, cujo valor é então exibido no console:
H e l l o
Outro exemplo pode ser a iteração sobre um array:
const people = ["Tom", "Sam", "Bob"];
for (const person of people) {
console.log(person);
}
Neste caso, o laço itera os elementos do array people. Cada elemento é colocado sequencialmente na constante person
. Em seguida, podemos exibir seu valor no console:
Tom Sam Bob