<h2>O que são Iteradores?</h2>
<p>Um iterador é um objeto que implementa dois métodos: <code>next()</code> e opcionalmente <code>return()</code> e <code>throw()</code>. O método <code>next()</code> retorna um objeto com duas propriedades: <code>value</code> (o valor atual) e <code>done</code> (booleano indicando se a iteração terminou). Iteradores permitem acessar elementos de uma coleção um por um, de forma controlada.</p>
<p>Para entender melhor, vejamos um exemplo prático. Criaremos um iterador simples que percorre números de 1 a 3:</p>
<pre><code class="language-javascript">function criarIteradorNumeros(max) {
let atual = 1;
return {
next() {
if (atual <= max) {
return { value: atual++, done: false };
}
return { done: true };
}
};
}
const iterador = criarIteradorNumeros(3);
console.log(iterador.next()); // { value: 1, done: false }
console.log(iterador.next()); // { value: 2, done: false }
console.log(iterador.next()); // { value: 3, done: false }
console.log(iterador.next()); // { done: true }</code></pre>
<h2>O Protocol Iterável e o Loop for...of</h2>
<p>Um objeto é <strong>iterável</strong> quando implementa o método <code>Symbol.iterator</code>, que retorna um iterador. Essa é a base do protocolo iterável do JavaScript, permitindo usar <code>for...of</code> e spread operator. Arrays, Strings e Maps já são iteráveis nativamente.</p>
<p>Vamos criar um objeto iterável customizado:</p>
<pre><code class="language-javascript">const minhaColecao = {
dados: ['A', 'B', 'C'],
[Symbol.iterator]() {
let indice = 0;
return {
next: () => {
if (indice < this.dados.length) {
return { value: this.dados[indice++], done: false };
}
return { done: true };
}
};
}
};
// Agora podemos usar for...of
for (const item of minhaColecao) {
console.log(item); // A, B, C
}
// E o spread operator
const array = [...minhaColecao];
console.log(array); // ['A', 'B', 'C']</code></pre>
<p>A vantagem é que você controla completamente como a iteração funciona, permitindo lógica customizada sem precisar expor toda a estrutura interna.</p>
<h2>Generators: Iteradores Simplificados</h2>
<p>Generators são funções especiais declaradas com <code>function*</code> que pausam a execução com <code>yield</code> e retomam quando <code>next()</code> é chamado. Elas retornam um iterador automaticamente, eliminando a necessidade de implementar manualmente <code>next()</code> e <code>Symbol.iterator</code>.</p>
<p>Um generator é fundamentalmente mais conciso. Veja como reescrever nosso exemplo anterior:</p>
<pre><code class="language-javascript">function* gerador() {
yield 1;
yield 2;
yield 3;
}
const gen = gerador();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { done: true }
// Também funciona com for...of
for (const valor of gerador()) {
console.log(valor); // 1, 2, 3
}</code></pre>
<h3>Generators com Lógica Complexa</h3>
<p>Generators brilham quando você precisa de lógica mais sofisticada. Vejamos um exemplo prático: gerar números Fibonacci infinitamente:</p>
<pre><code class="language-javascript">function* fibonacci() {
let [a, b] = [0, 1];
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
console.log(fib.next().value); // 5</code></pre>
<h3>Recebendo Valores em Generators</h3>
<p>O método <code>next()</code> pode receber argumentos que são retornados como valor de uma expressão <code>yield</code>. Isso permite comunicação bidirecional:</p>
<pre><code class="language-javascript">function* dialogo() {
const resposta1 = yield 'Qual é seu nome?';
console.log(Olá, ${resposta1}!);
const resposta2 = yield 'Qual é sua idade?';
console.log(Você tem ${resposta2} anos.);
}
const gen = dialogo();
console.log(gen.next().value); // "Qual é seu nome?"
console.log(gen.next('Maria').value); // "Qual é sua idade?" (imprime: Olá, Maria!)
gen.next(25); // imprime: Você tem 25 anos.</code></pre>
<h2>Casos de Uso Reais</h2>
<p>Generators são ideais para processar grandes volumes de dados sem carregar tudo na memória. Um exemplo clássico é ler um arquivo linha por linha:</p>
<pre><code class="language-javascript">function* lerLinhas(linhas) {
for (const linha of linhas) {
yield linha;
}
}
const dados = ['linha 1', 'linha 2', 'linha 3', 'linha 4'];
for (const linha of lerLinhas(dados)) {
console.log(linha); // processa uma por vez
}</code></pre>
<p>Outra aplicação importante é criar <strong>pipelines de transformação</strong>:</p>
<pre><code class="language-javascript">function* range(inicio, fim) {
for (let i = inicio; i < fim; i++) {
yield i;
}
}
function* map(iteravel, funcao) {
for (const item of iteravel) {
yield funcao(item);
}
}
function* filter(iteravel, predicado) {
for (const item of iteravel) {
if (predicado(item)) yield item;
}
}
// Uso encadeado
const resultado = filter(
map(range(1, 10), x => x * 2),
x => x > 5
);
for (const num of resultado) {
console.log(num); // 6, 8, 10, 12, 14, 16, 18
}</code></pre>
<h2>Conclusão</h2>
<p>Os pontos-chave são: <strong>iteradores</strong> são a base do protocolo iterável, permitindo controle fino sobre iteração; <strong>generators</strong> simplificam enormemente essa implementação usando <code>function*</code> e <code>yield</code>, tornando o código mais legível; e ambos economizam memória ao processar dados sob demanda, não carregando tudo de uma vez. Domine esses conceitos para escrever código JavaScript mais elegante e eficiente.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators" target="_blank" rel="noopener noreferrer">MDN - Iterators and Generators</a></li>
<li><a href="https://tc39.es/ecma262/#sec-generator-function-objects" target="_blank" rel="noopener noreferrer">ECMAScript Specification - GeneratorFunction</a></li>
<li><a href="https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/get-started/ch4.md" target="_blank" rel="noopener noreferrer">You Don't Know JS Yet - Generators</a></li>
<li><a href="https://javascript.info/generators" target="_blank" rel="noopener noreferrer">JavaScript.info - Generators</a></li>
</ul>