Melhores Práticas para Iteração em JavaScript

Melhores Práticas para Iteração em JavaScript

Este artigo explica as melhores práticas para iteração em JavaScript.

YouTube Video

Melhores Práticas para Iteração em JavaScript

Em JavaScript, é comum usar loops for para iteração. Aqui, forneceremos uma explicação detalhada das melhores práticas para usar loops for para escrever código eficiente e legível.

Escolha a Estrutura de Loop Adequada

O JavaScript oferece várias construções de loop, cada uma adequada para propósitos diferentes.

 1// Example of a for loop
 2for (let i = 0; i < 5; i++) {
 3    console.log(i);
 4}
 5
 6// Example of a for...of loop
 7const array = [10, 20, 30];
 8for (const value of array) {
 9    console.log(value);
10}
11
12// Example of a for...in loop
13const obj = { a: 1, b: 2, c: 3 };
14for (const key in obj) {
15    console.log(`${key}: ${obj[key]}`);
16}
17
18// Example of a while loop
19let count = 0;
20while (count < 5) {
21    console.log(count);
22    count++;
23}
  • A declaração for é adequada quando o número de iterações é predeterminado.
  • A declaração for...of é adequada para processar arrays e objetos iteráveis de forma concisa.
  • A declaração for...in é usada para iterar sobre as propriedades de um objeto. No entanto, não é adequado para arrays.
  • As declarações while e do...while são usadas para controlar loops com base em condições.

Utilizando o método forEach e a declaração for...of.

Ao iterar por um array, usar a declaração for para acessar o índice é comum, mas o método forEach ou a declaração for...of podem ser mais legíveis.

 1// Using a standard for loop
 2const array = ["apple", "banana", "cherry"];
 3for (let i = 0; i < array.length; i++) {
 4    console.log(array[i]);
 5}
 6
 7// Using forEach
 8array.forEach(item => console.log(item));
 9
10// Using for...of
11for (const item of array) {
12    console.log(item);
13}
  • A declaração for permite o gerenciamento explícito do índice durante a iteração.
  • O método forEach utiliza uma função de callback para processar cada elemento de forma concisa.
  • A declaração for...of é altamente legível e permite acesso direto a cada elemento de um array.

Otimize as Condições do Loop

Uma vez que a condição do loop é avaliada repetidamente, evitar cálculos desnecessários pode melhorar o desempenho.

 1const names = ["Alice", "Bob", "Charlie"];
 2const scores = [85, 92, 78];
 3
 4// Inefficient example
 5for (let i = 0; i < Math.min(names.length, scores.length); i++) {
 6    console.log(`${names[i]} scored ${scores[i]}`);
 7}
 8
 9// Efficient example
10for (let i = 0, len = Math.min(names.length, scores.length); i < len; i++) {
11    console.log(`${names[i]} scored ${scores[i]}`);
12}
  • Como mostrado neste exemplo, armazenar o resultado do cálculo em uma variável previamente permite uma execução de loop mais eficiente.
 1const scores = [85, 92, 78];
 2let sum = 0;
 3let sum2 = 0;
 4
 5// Inefficient example
 6for (let i = 0; i < scores.length; i++) {
 7    sum += scores[i];
 8}
 9console.log(`Total score : ${sum}`);
10
11// Efficient example
12for (let i = scores.length - 1; i >= 0; i--) {
13    sum2 += scores[i];
14}
15console.log(`Total score : ${sum2}`);
  • Como mostrado neste exemplo, inverter a condição pode ser mais eficiente em alguns casos.

Otimizando o Processamento de Loops

Como o processamento de loops é executado repetidamente, evitar cálculos desnecessários pode melhorar o desempenho.

 1const array = ["apple", "banana", "cherry"];
 2
 3// Inefficient example
 4for (let i = 0; i < 100; i++) {
 5    const element = document.querySelector("#myElement");
 6    element.textContent = `Count: ${i}`;
 7}
 8
 9// Efficient example
10const element = document.querySelector("#myElement");
11for (let i = 0; i < 100; i++) {
12    element.textContent = `Count: ${i}`;
13}
  • Neste exemplo, movendo o método querySelector para fora do loop, elimina-se cálculos repetidos desnecessários.

Esteja Atento ao Escopo

Use let ou const para garantir que as variáveis dentro do loop tenham o escopo apropriado. Como var é limitado ao escopo da função, pode causar comportamentos inesperados.

 1// Using let
 2for (let i = 0; i < 3; i++) {
 3    console.log(i);
 4}
 5
 6// Potential issue with var
 7for (var i = 0; i < 3; i++) {
 8    setTimeout(() => console.log(i), 1000); // 3, 3, 3
 9}
10
11// Using let to avoid the issue
12for (let i = 0; i < 3; i++) {
13    setTimeout(() => console.log(i), 1000); // 0, 1, 2
14}
  • var tem escopo de função, então após o loop i é 3, e todas as funções executadas por setTimeout retornam 3.
  • Usando let, o i dentro da função de callback setTimeout refere-se a um novo valor para cada loop, então 0, 1, 2 são exibidos como esperado.

Melhore a Legibilidade com Saídas Antecipadas

Para simplificar o processamento do loop, use break e continue de forma apropriada para melhorar a legibilidade.

 1// Example using break
 2for (let i = 0; i < 10; i++) {
 3    if (i === 5) {
 4        break; // Exit the loop
 5    }
 6    console.log(i);
 7}
 8
 9// Example using continue
10for (let i = 0; i < 10; i++) {
11    if (i % 2 === 0) {
12        continue; // Skip to the next iteration
13    }
14    console.log(i);
15}
  • Usar break permite terminar o processamento do loop no meio, pulando todas as iterações subsequentes.
  • Usar continue permite pular o processo do loop atual e passar para a próxima iteração.

Evite Aninhamentos Profundos

Aninhamentos profundos tornam o código mais difícil de ler, então procure manter o aninhamento raso usando retornos antecipados ou dividindo funcionalidades em funções.

 1// Deeply nested example
 2for (let i = 0; i < 5; i++) {
 3    for (let j = 0; j < 5; j++) {
 4        if (i + j > 5) {
 5            console.log(i, j);
 6        }
 7    }
 8}
 9
10// Improved using function decomposition
11function processPairs(i) {
12    for (let j = 0; j < 5; j++) {
13        if (i + j > 5) {
14            console.log(i, j);
15        }
16    }
17}
18
19for (let i = 0; i < 5; i++) {
20    processPairs(i);
21}
  • Neste exemplo, funções são usadas para reduzir a aninhamento.

Considere o tratamento de erros

Se houver a possibilidade de erros ocorrerem dentro do loop, implemente o tratamento adequado de erros.

 1const data = ["123", "abc", "456", "xyz"];
 2
 3// Without Error Handling
 4for (const item of data) {
 5    const result = parseInt(item);
 6    console.log(`Parsed value: ${result}`);
 7}
 8
 9// With Error Handling
10for (const item of data) {
11    try {
12        const result = parseInt(item);
13        if (isNaN(result)) {
14            throw new Error(`Invalid number: ${item}`);
15        }
16        console.log(`Parsed value: ${result}`);
17    } catch (error) {
18        console.error(`Error processing item: ${item}. ${error.message}`);
19    }
20}
  • Neste exemplo, o tratamento de erros é realizado para processar dados inválidos, detectando e relatando problemas.

Pontos a observar no processamento assíncrono

Ao lidar com processamento assíncrono em loops, o uso de async/await pode resultar em um código conciso e intuitivo.

 1const urls = ["https://example.com/1", "https://example.com/2"];
 2
 3// Proper handling of asynchronous operations
 4async function fetchUrls() {
 5    for (const url of urls) {
 6        const response = await fetch(url);
 7        const data = await response.json();
 8        console.log(data);
 9    }
10}
11
12fetchUrls();
  • Este código busca URLs do array urls de forma assíncrona, uma por uma, e processa os resultados no formato JSON. Usar async/await simplifica operações assíncronas, recuperando sequencialmente dados de cada URL e exibindo-os no console.

Compreenda a diferença entre a instrução for...of e forEach() no processamento assíncrono.

 1async function asyncTask(num) {
 2    return new Promise(resolve => {
 3        setTimeout(() => {
 4            console.log(`Task ${num} done`);
 5            resolve();
 6        }, 100);
 7    });
 8}
 9
10async function runWithForOf() {
11    console.log("Start for...of");
12    for (const num of [1, 2, 3]) {
13        await asyncTask(num);
14    }
15    console.log("End for...of");
16}
17
18async function runWithForEach() {
19    console.log("Start forEach");
20    [1, 2, 3].forEach(async num => {
21        await asyncTask(num);
22    });
23    console.log("End forEach");
24}
25
26async function executeExamples() {
27    await runWithForOf();
28    await runWithForEach();
29}
30
31executeExamples();
  • Ao lidar com o processamento assíncrono em loops, observe as diferenças de comportamento, como mostrado neste exemplo, entre o uso de for...of com async/await e o uso de forEach().

  • Com for...of, o código é executado sequencialmente e espera no await dentro do loop antes de continuar para a próxima iteração. Por outro lado, forEach() executa o processamento em paralelo.

Conclusão

A instrução for em JavaScript é uma ferramenta simples, mas poderosa. Ao aplicar as melhores práticas apresentadas aqui, você pode escrever um código eficiente e altamente legível. Preste atenção na escolha das estruturas de loop adequadas, no gerenciamento de escopo, no tratamento de erros e tenha como objetivo um código altamente sustentável.

Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.

YouTube Video