O ciclo for é uma das instruções mais usadas para executar alguma lógica repetidamente.
Em JavaScript, é composto pela palavra-chave for, um cabeçalho entre parênteses e um bloco de código que contém o corpo do ciclo, entre chavetas.
for (initialization; condition; step) {
// code that is executed repeatedly as long as the condition is
// true
}
A inicialização costuma criar uma variável contadora, a condição verifica se o ciclo deve continuar ou parar e o passo incrementa o contador no fim de cada repetição. As diversas partes do cabeçalho são separadas por pontos e vírgulas.
const list = ['a', 'b', 'c'];
for (let i = 0; i < list.length; i++) {
// code that should be executed for each item in the array
}
As três partes do cabeçalho são opcionais. Na prática, isto é raramente utilizado. Podes ler mais sobre isto na documentação da MDN.
Os ciclos for podem ser aninhados, por exemplo, para iterar sobre arrays aninhados (multidimensionais).
Certifica-te de que crias uma variável contadora diferente para cada ciclo.
const coords = [
[1, 2],
[4, 7],
[10, -3],
];
for (let i = 0; i < coords.length; i++) {
for (let j = 0; j < coords[i].length; j++) {
// do something with coords[i][j]
}
}
Dentro do corpo de um ciclo, podes usar a palavra-chave break para interromper por completo a execução do ciclo.
Em contrapartida, a palavra-chave continue interrompe apenas a execução da iteração atual e passa à seguinte.
Quando trabalhas com ciclos aninhados, break e continue aplicam-se sempre, por omissão, ao ciclo mais interno.
Podes usar rótulos para alterar esse comportamento.
Um rótulo é um nome de identificador seguido de dois pontos.
É colocado à frente do ciclo (ou por cima dele).
Depois, esse rótulo pode ser combinado com break ou continue para definir a que ciclo se aplica a instrução.
outer: for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
// ...
if (j > 5) {
continue outer;
}
// ...
}
}
Tens de ter cuidado para declarar corretamente a variável contadora quando trabalhas com código assíncrono.
Vejamos um exemplo em que somamos a variável contadora de forma assíncrona com setTimeout depois de esperar 1s.
Se declarares o contador com var, ou com let mas fora do cabeçalho, o código não dá o resultado esperado.
let sum = 0;
for (var i = 1; i < 4; i++) {
setTimeout(function () { sum += i; }, 1000);
}
// eventually sum will be 12 instead of 6 (1+2+3)
let sum = 0;
let i;
for (i = 1; i < 4; i++) {
setTimeout(function () { sum += i; }, 1000);
}
// same here, eventually sum will be 12 instead of 6 (1+2+3)
Nestes dois casos, o i não fica limitado ao âmbito de uma iteração específica do ciclo.
Quando a soma é calculada, o i já atingiu o seu valor final 4, o que faz com que a soma seja 4 + 4 + 4 = 12.
Podes evitar este problema declarando o contador com let dentro do cabeçalho.
Isto tem o efeito especial de dar a cada iteração a sua própria variável let i, limitada ao âmbito exato daquela execução do corpo do ciclo.
Assim, quando a soma é calculada mais tarde, cada função de callback refere-se à sua própria variável i, que ainda contém o valor correto.
let sum = 0;
for (let i = 1; i < 4; i++) {
setTimeout(function () { sum += i; }, 1000);
}
// eventually sum will be 6 (1+2+3) as expected