domingo, 19 de marzo de 2017

Nuevas características de ecma6 - Generadores e Iteradores

Hello!!! hoy hablaremos un poco de una nueva característica muy interesante en javascript (ecma6), los generadores.

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 iterador
element = 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
El operador spread (...) permite al generador ejecutar todos los valores que tenga; además con la desestructuración podemos asignar los valores a variables como se ve en el segundo ejemplo.

Y eso es todo por ahora, espero les haya parecido tan interesante como a mi :p keep coding!!!

No hay comentarios:

Publicar un comentario