O guia essencial para iteradores JavaScript

Resumo : neste tutorial, você aprenderá sobre iteradores JavaScript e como usá-los para processar uma sequência de dados com mais eficiência.

Os forproblemas do loop

Quando você tem uma matriz de dados, normalmente usa um for loop para iterar sobre seus elementos. Por exemplo:

let ranks = ['A', 'B', 'C'];

for (let i = 0; i < ranks.length; i++) {
    console.log(ranks[i]);
}Linguagem de código:  JavaScript  ( javascript )

O forloop usa a variável   ipara rastrear o índice do ranksarray. O valor dos   iincrementos cada vez que o loop é executado, desde que o valor de iseja menor que o número de elementos na ranksmatriz.

Este código é direto. No entanto, sua complexidade aumenta quando você aninha um loop dentro de outro loop. Além disso, acompanhar múltiplas variáveis ​​dentro dos loops é propenso a erros.

ES6 introduziu uma nova construção de loop chamada for...ofpara eliminar a complexidade do loop padrão e evitar os erros causados ​​pelo controle dos índices do loop.

Para iterar sobre os elementos do ranksarray, você usa a seguinte for...ofconstrução:

for(let rank of ranks) {
    console.log(rank);
}Linguagem de código:  JavaScript  ( javascript )

É for...ofmuito mais elegante que o forloop porque mostra a verdadeira intenção do código – iterar sobre um array para acessar cada elemento na sequência.

Além disso, o for...ofloop tem a capacidade de criar um loop sobre qualquer objeto iterável , não apenas um array.

Para entender o objeto iterável, você precisa primeiro entender os protocolos de iteração.

Protocolos de iteração

Existem dois protocolos de iteração: protocolo iterável e protocolo iterador .

Protocolo iterador

Um objeto é um iterador quando implementa uma interface (ou API) que responde a duas perguntas:

  • Sobrou algum elemento?
  • Se houver, qual é o elemento?

Tecnicamente falando, um objeto é qualificado como iterador quando possui um next()método que retorna um objeto com duas propriedades:

  •  done: um valor booleano que indica se há ou não mais elementos que possam ser iterados.
  •  value: o elemento atual.

Cada vez que você chama next(), ele retorna o próximo valor da coleção:

{ value: 'next value', done: false }Linguagem de código:  CSS  ( css )

Se você chamar o next()método após o último valor ter sido retornado, ele next()retornará o objeto de resultado da seguinte forma:

{done: true: value: undefined}Linguagem de código:  CSS  ( css )

O valor da donepropriedade indica que não há mais valor a ser retornado e o valor valueda propriedade está definido como undefined.

Protocolo iterável

Um objeto é iterável quando contém um método chamado [Symbol.iterator]que não aceita argumentos e retorna um objeto que está em conformidade com o protocolo do iterador.

O é um dos símbolos[Symbol.iterator] integrados bem conhecidos no ES6.

Iteradores

Como o ES6 fornece iteradores integrados para os tipos de coleção  Array, Set, e Map, você não precisa criar iteradores para esses objetos.

Se você tiver um tipo personalizado e quiser torná-lo iterável para poder usar a for...ofconstrução de loop, será necessário implementar os protocolos de iteração.

O código a seguir cria um Sequenceobjeto que retorna uma lista de números no intervalo de ( start, end) com um intervalentre os números subsequentes.

class Sequence {
    constructor( start = 0, end = Infinity, interval = 1 ) {
        this.start = start;
        this.end = end;
        this.interval = interval;
    }
    [Symbol.iterator]() {
        let counter = 0;
        let nextIndex = this.start;
        return  {
            next: () => {
                if ( nextIndex <= this.end ) {
                    let result = { value: nextIndex,  done: false }
                    nextIndex += this.interval;
                    counter++;
                    return result;
                }
                return { value: counter, done: true };
            }
        }
    }
};Linguagem de código:  JavaScript  ( javascript )

O código a seguir usa o Sequenceiterador em um for...ofloop:

let evenNumbers = new Sequence(2, 10, 2);

for (const num of evenNumbers) {
    console.log(num);
}Linguagem de código:  JavaScript  ( javascript )

Saída:

2
4
6
8
10

Você pode acessar explicitamente o [Symbol.iterator]()método conforme mostrado no script a seguir:

let evenNumbers = new Sequence(2, 10, 2);
let iterator = evenNumbers[Symbol.iterator]();

let result = iterator.next();

while( !result.done ) {
    console.log(result.value);
    result = iterator.next();
}Linguagem de código:  JavaScript  ( javascript )

Limpando

Além do next()método, [Symbol.iterator]()pode retornar opcionalmente um método chamado return().

O return()método é invocado automaticamente quando a iteração é interrompida prematuramente. É onde você pode colocar o código para limpar os recursos.

O exemplo a seguir implementa o return()método para o Sequenceobjeto:

class Sequence {
    constructor( start = 0, end = Infinity, interval = 1 ) {
        this.start = start;
        this.end = end;
        this.interval = interval;
    }
    [Symbol.iterator]() {
        let counter = 0;
        let nextIndex = this.start;
        return  {
            next: () => {
                if ( nextIndex <= this.end ) {
                    let result = { value: nextIndex,  done: false }
                    nextIndex += this.interval;
                    counter++;
                    return result;
                }
                return { value: counter, done: true };
            },
            return: () => {
                console.log('cleaning up...');
                return { value: undefined, done: true };
            }
        }
    }
}Linguagem de código:  JavaScript  ( javascript )

O trecho a seguir usa o Sequenceobjeto para gerar uma sequência de números ímpares de 1 a 10. No entanto, ele interrompe prematuramente a iteração. Como resultado, o return()método é invocado automaticamente.

let oddNumbers = new Sequence(1, 10, 2);

for (const num of oddNumbers) {
    if( num > 7 ) {
        break;
    }
    console.log(num);
}Linguagem de código:  JavaScript  ( javascript )

Saída:

1
3
5
7
cleaning up...

Neste tutorial, você aprendeu sobre o iterador JavaScript e como usar os protocolos de iteração para implementar lógica de iteração customizada.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *