Esta tradução está incompleta. Por favor, ajude a traduzir este artigo.

As linguagens de programação são muito úteis para concluir rapidamente tarefas repetitivas, desde vários cálculos básicos até praticamente qualquer outra situação em que você tenha muitos itens semelhantes para manipular. Aqui, veremos as estruturas de loop disponíveis no JavaScript que ajudam com essas necessidades..

Prerequisitos: Conhecimento básico em informática, um básico entendimento  de HTML e CSS, JavaScript first steps.
Objectivo: Entender como usar loops em JavaScript.

Mantenha-me no loop(laço)

Loops, loops, loops. Além de estarem associados a populares cereais matinais, montanhas-russas e produção musical, eles também são um conceito importante na programação. O loop de programação é como fazer a mesma coisa repetidas vezes - o que é chamado de iteração na linguagem de programação.

Vamos considerar o caso de um agricultor que quer se certificar de que ele terá comida suficiente para alimentar sua família durante a semana. Ele pode usar o seguinte loop para conseguir isso:


Um loop geralmente possui um ou mais dos seguintes itens:

  •  O contador, que é inicializado com um certo valor - este é o ponto inicial do loop ("Iniciar: não tenho comida", figura acima).
  • A condição de saída, que é o critério no qual o loop pára - geralmente o contador atinge um certo valor. Isso é ilustrado por "Tenho comida suficiente?",  na figura acima. Vamos dizer que ele precisa de 10 porções de comida para alimentar sua família.
  • Um iterador, que geralmente incrementa o contador em uma pequena quantidade a cada loop, sucessivamente, até atingir a condição de saída. Nós não ilustramos explicitamente isso acima, mas poderíamos pensar sobre o agricultor ser capaz de coletar 2 porções de comida por hora. Depois de cada hora, a quantidade de comida que ele coletou é incrementada em dois, e ele verifica se ele tem comida suficiente. Se ele atingiu 10 porções (a condição de saída), ele pode parar de coletar e ir para casa.

No seu pseudocode, isso seria algo como o seguinte:

loop(food = 0; foodNeeded = 10) {
  if (food = foodNeeded) {
    exit loop;
    // Nós temos comida o suficiente, Vamos para casa
  } else {
    food += 2; // Passe uma hora coletando mais 2 alimentos(food)
    // loop será executado novamente
  }
}

Assim, a quantidade de comida necessária é fixada em 10, e o montante que o agricultor tem atualmente é fixado em 0. Em cada iteração do ciclo, verificamos se a quantidade de alimento que o agricultor tem é igual à quantidade que ele precisa. Se assim for, podemos sair do loop. Se não, o agricultor gasta mais uma hora coletando duas porções de comida, e o laço é executado novamente.

Porque se importar?

Neste ponto, você provavelmente já entendeu o conceito de alto nível por trás dos loops, mas provavelmente está pensando "OK, ótimo, mas como isso me ajuda a escrever um código JavaScript melhor?" Como dissemos anteriormente, os loops têm tudo a ver com fazer a mesma coisa repetidas vezes, o que é ótimo para concluir rapidamente tarefas repetitivas.

Muitas vezes, o código será um pouco diferente em cada iteração sucessiva do loop, o que significa que você pode completar toda uma carga de tarefas que são semelhantes, mas não são totalmente iguais — se você tem muitos cálculos diferentes para fazer, e você quer fazer um diferente do outro, e não o mesmo repetidamente!

Vejamos um exemplo para ilustrar perfeitamente por que os loops são uma coisa tão boa. Digamos que quiséssemos desenhar 100 círculos aleatórios em um elemento  <canvas>  (pressione o botão Atualizar para executar o exemplo várias vezes para ver os conjuntos aleatórios diferentes):

Você não precisa entender todo esse código por enquanto, mas vamos ver a parte do código que realmente desenha os 100 círculos:

for (var i = 0; i < 100; i++) {
  ctx.beginPath();
  ctx.fillStyle = 'rgba(255,0,0,0.5)';
  ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
  ctx.fill();
}
  • random(), definido anteriormente no código, retorna um número inteiro entre 0 e x-1.
  • WIDTH e HEIGHT são a largura e a altura da janela interna do navegador. 

Você deve ter notado - estamos usando um loop para executar 100 iterações desse código, cada uma delas desenhando um círculo em uma posição aleatória na página. A quantidade de código necessária seria a mesma se estivéssemos desenhando 100 círculos, 1.000 ou 10.000. Apenas um número tem que mudar.

Se não estivéssemos usando um loop aqui, teríamos que repetir o seguinte código para cada círculo que queríamos desenhar:

ctx.beginPath();
ctx.fillStyle = 'rgba(255,0,0,0.5)';
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
ctx.fill();

Isso ficaria muito chato, difícil e lento de manter. Loops são realmente os melhores.

O for loop padrão

Vamos começar a explorar alguns exemplos específicos de construções de loop. O primeiro e que você usará na maior parte do tempo, é o loop for - ele tem a seguinte sintaxe:

for (inicializador; condição-saída; expressão-final) {
  // código para executar
}

Aqui nós temos:

  1. A palavra-chave for, seguido por parênteses.
  2. Dentro do parênteses temos três itens, sepados por ponto e vírgula:
    1. O inicializador— geralmente é uma variável configurada para um número, que é incrementado para contar o número de vezes que o loop foi executado. É também por vezes referido como uma variável de contador.
    2. condição-saída — como mencionado anteriormente, aqui é definido qundo o loop deve parar de executar. Geralmente, essa é uma expressão que apresenta um operador de comparação, um teste para verificar se a condição de saída foi atendida.
    3. A expressão-final — isso sempre é avaliado (ou executado) cada vez que o loop passou por uma iteração completa. Geralmente serve para incrementar (ou, em alguns casos, decrementar) a variável do contador, aproximando-a do valor da condição de saída.
  3. Algumas chaves contêm um bloco de código - esse código será executado toda vez que o loop for iterado.

Vejamos um exemplo real para podermos visualizar o que isso faz com mais clareza.

var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin'];
var info = 'My cats are called ';
var para = document.querySelector('p');

for (var i = 0; i < cats.length; i++) {
  info += cats[i] + ', ';
}

para.textContent = info;

Isso nos dá a seguinte saída:

Nota: Você pode encontrar este código de exemplo no GitHub (também veja em execução ).

Aqui mostra um loop sendo usado para iterar os itens em uma matriz e fazer algo com cada um deles - um padrão muito comum em JavaScript. Aqui:

  1. O iterador, i, começa em 0 (var i = 0).
  2. Foi dito para executar até que não seja menor que o comprimento do array dos gatos. Isso é importante - a condição de saída mostra a condição sob a qual o loop ainda será executado. No caso, enquanto i < cats.length  for verdadeiro, o loop continuará executando.
  3. Dentro do loop, nós concatenamos o item de loop atual (cats[i] é cats[o nome do item que está iterado no momento]) junto com uma vírgula e um espaço, no final da variável info . Assim:
    1. Durante a primeira execução, i = 0, então cats[0] + ', ' será concatenado na variável info ("Bill").
    2. Durante a segunda execução, i = 1, so cats[1] + ', ' será concatenado na variável info ("Jeff, ")
    3. E assim por diante. Após cada execução do loop, 1 será adicionado à i (i++), então o processo será iniciado novamente.
  4. Quando i torna-se igual a cats.length, o loop é interrompido e o navegador passará para o próximo trecho de código abaixo do loop.

Nota:Nós fizemos a condição de saída i < cats.length, e não i <= cats.length, porque os computadores contam a partir de 0, não 1 - estamos começando i em 0, e indo até i = 4 (o index do último item do array). cats.length retorna 5, pois há 5 itens no array, mas não queremos chegar até  i = 5, pois isso retornaria  undefined para o último item (não há nenhum item  no índice 5 do array). Então, portanto, queremos ir até 1 a menos de  cats.length (i <), não é o mesmo que cats.length (i <=).

Nota: Um erro comum nas condições de saída é usá-las "igual a" (===) em vez de dizer "menor ou igual a" (<=). Se quiséssemos executar nosso loop até  i = 5, a condição de saída precisaria ser  i <= cats.length. Se nós setarmos para  i === cats.length, o loop não seria executado em todos, porque  i não é igual a 5 na primeira iteração do loop, a execução pararia imediatamente.

Um pequeno problema que nos resta é que a sentença de saída final não é muito bem formada:

My cats are called Bill, Jeff, Pete, Biggles, Jasmin,

Neste caso, queremos alterar a concatenação na iteração final do loop, para que não tenhamos uma vírgula no final da frase. Bem, não há problema - podemos muito bem inserir uma condicional dentro do nosso loop for para lidar com este caso especial:

for (var i = 0; i < cats.length; i++) {
  if (i === cats.length - 1) {
    info += 'and ' + cats[i] + '.';
  } else {
    info += cats[i] + ', ';
  }
}

Nota: Você pode encontrar este código de exemplo no GitHub (também veja em execução ).

Importante: Com for - como acontece com todos os loops - você deve certificar-se de que o inicializador está iterado(configurado) para que ele atinja a condição de saída. Caso contrário, o loop continuará indefinidamente executando e o navegador irá forçá-lo a parar ou falhará. Isso é chamado de loop infinito.

Saindo do loop com o break

Se você quiser sair de um loop antes que todas as iterações sejam concluídas, você poderá usar a instrução break. Nós já encontramos isso em um artigo anterior, quando observamos as instruções switch - quando um determinado caso é atendido em uma condição do switch e que corresponde à expressão de entrada informada, a instrução break sai imediatamente da instrução switch e passa para o trecho de código seguinte.

É o mesmo com loops  — um comando  break  irá imediatamente sair do loop e fazer o navegador passar para o código seguinte.

Digamos que quiséssemos pesquisar por uma variedade de contatos e números de telefone e retornar apenas o número que queríamos encontrar? Primeiro, algum HTML simples  — um texto <input> permitindo-nos iserir um nome para pesquisar, <button> elemento para submeter a pesquisa e um <p> elemento para mostrar o resultado em:

<label for="search">Search by contact name: </label>
<input id="search" type="text">
<button>Search</button>

<p></p>

Agora para no JavaScript:

var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975'];
var para = document.querySelector('p');
var input = document.querySelector('input');
var btn = document.querySelector('button');

btn.addEventListener('click', function() {
  var searchName = input.value;
  input.value = '';
  input.focus();
  for (var i = 0; i < contacts.length; i++) {
    var splitContact = contacts[i].split(':');
    if (splitContact[0] === searchName) {
      para.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.';
      break;
    } else {
      para.textContent = 'Contact not found.';
    }
  }
});

  1. Primeiramente, temos algumas definições de variáveis —  temos um array com as informações dos contatos, cada item é uma string e contém um nome e um número de telefone separados por dois pontos.
  2. Em seguida, anexamos um ouvinte de evento ao botão (btn),  de modo que quando ele é pressionado, algum código é invocado para executar a pesquisa e retornar os resultados.
  3. Armazenamos o valor que foi inserido no input de texto em uma variável chamada  searchName, antes de limpar a entrada de texto e focar novamente, deixando o campo pronto para a próxima pesquisa.
  4. Agora, na parte interessante, o loop for:
    1. Iniciamos o contador em 0, executamos o loop até que o contador não seja menor que  contacts.length, e incrementamos i com 1 depois e cada iteração do loop.
    2. Dentro do loop, primeiro dividimos o contato atual (contacts[i]) no caractere " : " e armazenamos os dois valores resultantes em uma matriz chamada  splitContact.
    3. Em seguida, usamos uma instrução condicional para testar se o  splitContact[0] (nome do contato) é igual ao  searchName. Se for igual, inserimos uma string no parágrafo para mostrar em tela qual é o número do contato e usamos o break para encerrar o loop.
  5. Após (contacts.length-1) iterações, se o nome do contato não corresponder à pesquisa inserida, o texto do parágrafo será definido como "Contato não encontrado" e o loop continuará a iterar.

Nota: Você pode encontrar este código de exemplo no GitHub (também veja em execução ).

Ignorando iterações com continue

A instrução continue funciona de maneira semelhante ao  break, mas ao invés de sair inteiramente do loop, ele pula para a próxima iteração do loop. Vejamos outro exemplo que usa um número como entrada e retorna apenas os números que são quadrados de inteiros (números inteiros).

O HTML é basicamente o mesmo do último exemplo - uma entrada de texto simples e um parágrafo para saída. O JavaScript é basicamente o mesmo, embora o próprio loop seja um pouco diferente:

var num = input.value;

for (var i = 1; i <= num; i++) {
  var sqRoot = Math.sqrt(i);
  if (Math.floor(sqRoot) !== sqRoot) {
    continue;
  }

  para.textContent += i + ' ';
}

Aqui está a saída:

  1. Nesse caso, a entrada deve ser um número (num). O loop for recebe um contador começando em 1 (como não estamos interessados em 0 neste caso), uma condição de saída que diz que o loop irá parar quando o contador se tornar maior que o input num, e um iterador que adiciona 1 ao contador a cada vez.
  2. Dentro do loop, encontramos a raiz quadrada de cada número usando Math.sqrt(i), e, em seguida, verificamos se a raiz quadrada é um inteiro, testando se é igual a ela mesma quando foi arredondada para o inteiro mais próximo é o que Math.floor() faz com o número que é passado).
  3. Se a raiz quadrada e a raiz quadrada arredondada não forem iguais (! ==), isso significa que a raiz quadrada não é um número inteiro, portanto, não estamos interessados nela. Nesse caso, usamos a instrução continue para pular para a próxima iteração de loop sem registrar o número em nenhum lugar.
  4. Se a raiz quadrada é um inteiro, nós pulamos o bloco if inteiramente para que a instrução continue não seja executada; em vez disso, concatenamos o valor i atual mais um espaço até o final do conteúdo do parágrafo.

Note: Você pode encontrar este código de exemplo no GitHub (também veja em execução ).

while e o do ... while

for não é o único tipo de loop disponível em JavaScript. Na verdade, existem muitos outros, embora você não precise entender tudo isso agora, vale a pena dar uma olhada na estrutura dos outros tipos de loops para que você possa reconhecer a mesma lógica na funcionalidade porém empregada de uma forma diferente.

Primeiro, vamos dar uma olhada no while loop. A sintaxe deste loop é assim:

inicializador
while (condição-saída) {
  // code to run

  expressão-final
}

While funciona de maneira muito semelhante ao loop for, exceto que a variável inicializadora é definida antes do loop, e a expressão final é incluída dentro do loop após o código a ser executado - em vez de esses dois itens serem incluídos dentro dos parênteses. A condição de saída está incluída dentro dos parênteses, que são precedidos pela palavra-chave while e não por for.

 

Os mesmos três itens ainda estão presentes, e eles ainda são definidos na mesma ordem do loop for - isso faz sentido, já que você ainda precisa ter um inicializador definido antes de poder verificar se ele atingiu a condição de saída ; a condição final é então executada após o código dentro do loop ser executado (uma iteração foi concluída), o que só acontecerá se a condição de saída ainda não tiver sido atingida.

Vamos dar uma olhada novamente no nosso exemplo de lista de gatos, que reescrevemos para usar um loop while:

 

var i = 0;

while (i < cats.length) {
  if (i === cats.length - 1) {
    info += 'and ' + cats[i] + '.';
  } else {
    info += cats[i] + ', ';
  }

  i++;
}

Nota: Isso ainda funciona da mesma forma esperada — dê uma olhada no código em execução  (também veja o código fonte completo).

do...while loop é muito semelhante, mas fornece uma variação na estrutura while:

initializer
do {
  // code to run

  final-expression
} while (exit-condition)

 

Nesse caso, o inicializador novamente vem em primeiro lugar, antes que o loop seja iniciado. A palavra-chave precede diretamente as chaves que contêm o código a ser executado e a expressão final.

O diferenciador aqui é que a condição de saída vem depois de todo o resto, envolvida em parênteses e precedida por uma palavra-chave while. Em um loop do ... while, o código dentro das chaves é sempre executado uma vez antes da verificação ser feita para ver se deve ser executada novamente (no while e para, a verificação vem primeiro, então o código pode nunca ser executado ).

Vamos reescrever nosso exemplo de listagem de gato novamente para usar um loop do ... while:

 

var i = 0;

do {
  if (i === cats.length - 1) {
    info += 'and ' + cats[i] + '.';
  } else {
    info += cats[i] + ', ';
  }

  i++;
} while (i < cats.length);

Nota: Novamente, isso funciona exatamente como esperado - dê uma olhada nele executando no GitHub (veja também o código fonte completo).

Importante: Com while e do ... while - como em todos os loops - você deve certificar-se de que o inicializador esteja iterado para que ele atinja a condição de saída. Caso contrário, o loop continuará indefinidamente e o navegador irá forçá-lo a parar ou falhará. Isso é chamado de loop infinito.

Active learning: Launch countdown!

In this exercise, we want you to print out a simple launch countdown to the output box, from 10 down to Blast off. Specifically, we want you to:

  • Loop from 10 down to 0. We've provided you with an initializer — var i = 10;.
  • For each iteration, create a new paragraph and append it to the output <div>, which we've selected using var output = document.querySelector('.output');. In comments, we've provided you with three code lines that need to be used somewhere inside the loop:
    • var para = document.createElement('p'); — creates a new paragraph.
    • output.appendChild(para); — appends the paragraph to the output <div>.
    • para.textContent = — makes the text inside the paragraph equal to whatever you put on the right hand side, after the equals sign.
  • Different iteration numbers require different text to be put in the paragraph for that iteration (you'll need a conditional statement and multiple para.textContent = lines):
    • If the number is 10, print "Countdown 10" to the paragraph.
    • If the number is 0, print "Blast off!" to the paragraph.
    • For any other number, print just the number to the paragraph.
  • Remember to include an iterator! However, in this example we are counting down after each iteration, not up, so you don't want i++ — how do you iterate downwards?

If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.

Active learning: Filling in a guest list

In this exercise, we want you to take a list of names stored in an array, and put them into a guest list. But it's not quite that easy — we don't want to let Phil and Lola in because they are greedy and rude, and always eat all the food! We have two lists, one for guests to admit, and one for guests to refuse.

Specifically, we want you to:

  • Write a loop that will iterate from 0 to the length of the people array. You'll need to start with an initializer of  var i = 0;, but what exit condition do you need?
  • During each loop iteration, check if the current array item is equal to "Phil" or "Lola" using a conditional statement:
    • If it is, concatenate the array item to the end of the refused paragraph's textContent, followed by a comma and a space.
    • If it isn't, concatenate the array item to the end of the admitted paragraph's textContent, followed by a comma and a space.

We've already provided you with:

  • var i = 0; — Your initializer.
  • refused.textContent += — the beginnings of a line that will concatenate something on to the end of refused.textContent.
  • admitted.textContent += — the beginnings of a line that will concatenate something on to the end of admitted.textContent.

Extra bonus question — after completing the above tasks successfully, you will be left with two lists of names, separated by commas, but they will be untidy — there will be a comma at the end of each one. Can you work out how to write lines that slice the last comma off in each case, and add a full stop to the end? Have a look at the Useful string methods article for help.

If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.

Which loop type should you use?

For basic uses, for, while, and do...while loops are largely interchangeable. They can all be used to solve the same problems, and which one you use will largely depend on your personal preference — which one you find easiest to remember or most intuitive. Let's have a look at them again.

First for:

for (initializer; exit-condition; final-expression) {
  // code to run
}

while:

initializer
while (exit-condition) {
  // code to run

  final-expression
}

and finally do...while:

initializer
do {
  // code to run

  final-expression
} while (exit-condition)

We would recommend for, at least to begin with, as it is probably the easiest for remembering everything — the initializer, exit-condition, and final-expression all have to go neatly into the parentheses, so it is easy to see where they are and check that you aren't missing them.

Note: There are other loop types/features too, which are useful in advanced/specialized situations and beyond the scope of this article. If you want to go further with your loop learning, read our advanced Loops and iteration guide.

Conclusion

This article has revealed to you the basic concepts behind, and different options available when, looping code in JavaScript. You should now be clear on why loops are a good mechanism for dealing with repetitive code, and be raring to use them in your own examples!

If there is anything you didn't understand, feel free to read through the article again, or contact us to ask for help.

See also

 

In this module

 

Etiquetas do documento e colaboradores

Colaboradores desta página: recofka
Última atualização por: recofka,