Artigo original: JavaScript Loops Explained: For Loop, While Loop, Do...while Loop, and More

Os laços são usados em JavaScript para realizar tarefas repetidas com base em uma condição. As condições tipicamente retornam true ou false. Um laço continuará em execução até que a condição definida retorne false.

Laço for

Sintaxe

for (inicialização; condição; expressãoFinal) {
  // instruções a serem executadas repetidamente
}

O laço for consiste em três expressões e uma sequência de instruções:

  • inicialização - esta expressão é executada antes da execução do primeiro laço, sendo geralmente usada para criar um contador. A variável criada aqui fica no escopo do laço. Tão logo o laço se encerre, ela é destruída.
  • condição - esta expressão é verificada a cada iteração antes da execução do laço. Se ela for true, as instruções ou o código do laço é executado. Se ela for false, o laço é interrompido. Se essa expressão for omitida, será sempre true.
  • expressãoFinal - esta expressão é executada após cada iteração do laço. Ela é usada normalmente para incrementar um contador, mas também pode ser usada para decrementá-lo.
  • instruções - o código dentro do bloco a ser repetido no laço. Pode ser uma única ou várias linhas de código.

Qualquer uma das três expressões ou mesmo as próprias instruções – o código dentro do bloco – podem ser omitidas.

Laços for são normalmente usados para repetir instruções/executar código por um número definido de vezes. Além disso, é possível usar a instrução break para sair do laço precocemente, antes de a expressão de condição ser false.

Exemplos

1. Iterar por números inteiros de 0 a 8:

for (let i = 0; i < 9; i++) {
  console.log(i);
}

// Resultado:
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8

2. Use break para sair de um laço for antes de a expressão da condição ser false:

for (let i = 1; i < 10; i += 2) {
  if (i === 7) {
    break;
  }
  console.log('Número total de elefantes: ' + i);
}

// Resultado:
// Número total de elefantes: 1
// Número total de elefantes: 3
// Número total de elefantes: 5

Armadilha comum: exceder os limites de um array

Ao iterar por um array, é fácil exceder os limites dele acidentalmente. Por exemplo, seu laço pode tentar fazer referência ao 4º elemento de um array que tem apenas 3 elementos:

const arr = [ 1, 2, 3 ];

for (let i = 0; i <= arr.length; i++) {
  console.log(arr[i]);
}

// Resultado:
// 1
// 2
// 3
// undefined

Há duas maneiras de consertar esse código: definir a expressão de condição como i < arr.length ou i <= arr.length - 1.

Laço for...in

Sintaxe

for (variável in objeto) {
  // instruções
}

O laço for...in itera pelas propriedades de um objeto. Para cada propriedade, as instruções dentro do laço são executadas.

Exemplos

1. Iterar pelas propriedades de um objeto e imprimir suas chaves e valores no console:

const capitais = {
  a: "Atenas",
  b: "Belgrado",
  c: "Cairo"
};

for (let chave in capitais) {
  console.log(chave + ": " + capitais[chave]);
}

// Resultado:
// a: Atenas
// b: Belgrado
// c: Cairo

Armadilha comum: comportamento inesperado ao iterar por um array

Embora você possa usar um laço for...in para iterar por um array, é recomendado usar um laço for ou for...of nesse caso.

O laço for...in pode iterar por arrays e objetos semelhantes a um array, mas nem sempre pode acessar os índices de um array em ordem.

Além disso, o laço for...in retorna todas as propriedades e propriedades herdadas de um array ou de um objeto semelhante a um array, o que pode levar a um comportamento inesperado.

Por exemplo, este laço simples funciona de acordo com o que é esperado:

const array = [1, 2, 3];

for (const i in array) {
  console.log(i);
}

// 0
// 1
// 2

Porém, se algo como uma biblioteca do JS que você está usando modificar o protótipo de Array diretamente, um laço for...in também fará a iteração por ele:

const array = [1, 2, 3];

Array.prototype.umMetodoQualquer = true;

for (const i in array) {
  console.log(i);
}

// 0
// 1
// 2
// umMetodoQualquer

Embora modificar protótipos somente leitura, como Array ou Object, diretamente não seja uma boa prática, isso pode ser o problema de algumas bibliotecas ou bases de código.

Além disso, como for...in é destinado a objetos, ele é muito mais lento com arrays do que os outros laços.

Em resumo, lembre-se de usar os laços for...in somente para iterar por objetos, não por arrays.

Laço for...of

Sintaxe

for (variável of objeto) {
  // instruções
}

O laço for...of itera pelos valores de muitos tipos de iteráveis, incluindo arrays e tipos especiais de coleções, como Set e Map. Para cada valor no objeto iterável, as instruções dentro do laço são executadas.

Exemplos

1. Iterar por um array:

const arr = [ "Fred", "Tom", "Bob" ];

for (let i of arr) {
  console.log(i);
}

// Resultado:
// Fred
// Tom
// Bob

2. Iterar por um Map:

const m = new Map();
m.set(1, "preto");
m.set(2, "vermelho");

for (let n of m) {
  console.log(n);
}

// Resultado:
// [1, preto]
// [2, vermelho]

3. Iterar por um Set:

const s = new Set();
s.add(1);
s.add("vermelho");

for (let n of s) {
  console.log(n);
}

// Resultado:
// 1
// vermelho

Laço while

Sintaxe

while (condição) {
  // instruções
}

O laço while começa avaliando a condição. Se condition for true, o código dentro do bloco será executado. Se a condição for false, o código dentro do bloco não será executado e o laço se encerra.

Exemplos:

  1. Quando uma variável for inferior a 10, imprima-a no console e some a ela mais 1:
let i = 1;

while (i < 10) {
  console.log(i);
  i++;
}

// Resultado:
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9

Laço do...while

Sintaxe:

do {
  // instruções
} while (condição);

O laço do...while é fortemente associado ao laço while. Em um laço do...while, a expressão da condição é verificada ao final de cada iteração do laço, em vez de no começo, antes de o laço ser executado.

Isso significa que o código em um laço do...while com certeza será executado pelo menos uma vez, mesmo se a expressão da condição já for avaliada como false.

Exemplo:

  1. Enquanto uma variável for inferior a 10, imprima-a no console e some a ela mais 1:
let i = 1;

do {
  console.log(i);
  i++;
} while (i < 10);

// Resultado:
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9

2. Enviar para um array, mesmo se a condição for true:

const myArray = [];
let i = 10;

do {
  myArray.push(i);
  i++;
} while (i < 10);

console.log(myArray);

// Resultado:
// [10]