Los generadores son funciones especiales que pueden pausar su ejecución, luego volver al punto donde se quedaron, recordando su scope y seguir retornando valores.

Estos se utilizan para guardar la totalidad de datos infinitos, a través de una función matemática a valores futuros. De esta manera ocupan poca memoria, con respecto a si creamos un array u objeto.

Cómo utilizar generadores

La sintaxis de los generadores comprende lo siguiente:

Si el generador se lo invoca y ha retornado todos sus valores de yield, entonces devolverá el objeto con las propiedades value con undefined y un done con true.

// Declaración
function*nombre(parámetros){
yield (primer valor retornado)
yield (segundo valor retornado)
    ...
    yield (último valor retornado)

}

//Crear el generador
const generador = nombre(argumentos)

// Invocacioens
generador.next().value //primer valor retornado
generador.next().value //segundo valor retornado
...
generador.next().value //último valor retornado

Ejemplo de un generador

Por ejemplo, creemos un generador para retornar tres valores.

function*generator(){
yield 1
yield 2
yield 3
}

const generador = generator()

generador.next().value //1
generador.next().value //2
generador.next().value //3
generador.next() // {value: undefined, done: true}

Cómo utilizar for of y for in

Existen dos nuevas formas de utilizar ciclos repetitivos. El bucle for valor of iterable recorre iterables, como arrays, MapSet e incluso un generador.

El valor es cada elemento del iterable puede tener cualquier nombre, por eso se inicia con let nombre.

const array = [5, 4, 3, 2, 1]

for (let numeroof array) {
  console.log(numero) // 5 4 3 2 1
}

Sin embargo, debes tener en cuenta que solo podrás acceder a sus valores, y no a sus referencias, por lo que si quieres cambiar los elementos del array, necesitarás un índice array[indice].

for (let numeroof array) {
  valor *= 2
  console.log(numero) // 10 8 6 4 2
}

console.log(array) // [ 5, 4, 3, 2, 1 ]