En términos simples, un generador es una función que genera una serie de valores, con la particularidad de que no todos se generan al mismo tiempo, sino, de acuerdo a lo que se solicite. Es necesario pedir explicitamente valores a un generador, y el generador nos respondera con un nuevo valor o nos notificará que no existen más valores que retornar.
Además, un iterador es un objeto que sabe como acceder a los elementos de una colección uno a uno y que mantiene un registro de su posición en la secuencia :O. Los iteradores proveen el método next() para obtener el siguiente valor de la secuencia. next() devuelve un objeto con las propiedades done y value;
Una característica muy particular de los generadores es que cuando devuelven un valor, no téminan su labor como una función normal, sino que simplemente entran en un estado de suspensión, luego, cuando solicitamos un nuevo valor, el mismo generador reanuda su labor donde se detuvo anteriormente para luego volver a detenerse :O
Dado que siempre es mucho más sencillo entender algo con ejemplos, escribiremos una función que vaya generando números múltiplos de 3 primero y de siete a continuación.
// es necesario utilizar polyfills para que los generadores funcionen import 'babel-polyfill'; console.log('Iniciando pruebas con generadores'); // agregamos un * para crear un generador function* generador() { for(let i = 1; i <= 3; i++) { // utilizamos yield para devolver un valor // y pausar la ejecución del generador yield i * 3; } for(let i = 1; i <= 3; i++) { yield i * 7; } } console.log('\nPrimer bucle while\n'); // obtenemos el iterador del generador const iterator = generador(); let element; do{ // obtenemos un valor del iteradorelement = iterator.next();console.log(element); // cuando no hay mas elementos nos detenemos (element.done === true) } while(!element.done); console.log('\nSegundo bucle while\n'); const iterator2 = generador(); let element2; while(!(element2 = iterator2.next()).done ) { console.log(element2); }
Para definir un generador simplemente le agregamos un * a la palabra reservada function (function*). Con esto ya tenemos definido un generador y podemos utilizar la palabra reservada yield para devolver valores. Al llamar a la función no estamos ejecutandola, simplemente estamos creando un iterador, y ya con el iterador podemos utilizar next() para obtener un valor.
Como podemos ver en la imagen, obtenemos los valores del generador correctamente y cuando ya no existen más valores, la propiedad done es true.
Resultado de la ejecución del script |
Veamos otro ejemplo interesante, ahora realizaremos la iteración del generador con for-of y revisaremos el operador de desestructuración:
import 'babel-polyfill'; // definimos el generador function* generador() { yield 'Hola '; yield 'Mundo '; yield 'Con '; yield 'Generadores '; } console.log('============= Iterando con for of ============='); for (let palabra of generador()) { console.log(palabra); } console.log('\n============= Con el operador de propagación ============='); // ... permite a al generador expandirse y se almacena en arr const arr = [...generador()]; console.log(arr) console.log('\n============= Desestructurando ============='); // propaga el generador en los valores de p1 a p4 (el generador tiene 4 yields) // como no existe un quinto valor en el generador p5 imprime undefined const [p1, p2, p3, p4, p5] = [...generador()] console.log(p1); console.log(p2); console.log(p3); console.log(p4); // imprimira indefinido porque el generador solamente devuelve cuatro valores console.log(p5);
El resultado del proceso es:
Resultado del proceso |
Y eso es todo por ahora, espero les haya parecido tan interesante como a mi :p keep coding!!!
No hay comentarios:
Publicar un comentario