/ ECMAScript6

Funciones Generadoras en ECMAScript6

Como posiblemente sabes, ECMAScript6 es la nueva versión del estándar que utilizará JavaScript a partir de junio de 2015. Hablé de ello en una anterior entrada con algunas de las novedades que trae el estándar.

Recientemente he visto otras de las novedades del estándar, las funciones generadoras (Generators). Son funciones especiales (también se declaran de manera diferente con function *) y de las que se puede salir y entrar varias veces con resultados diferentes. Me ha parecido interesante, y quería compartirlo

Llamar a un Generator no ejecuta la función completa inmediatamente, si no que devuelve un objeto Iterator el cúal devuelve el valor del iterador o delega a otra función Generator a través de la variable yield. NOs serviremos del método next() para seguir iterando.

yield es una palabra reservadaque devuelve en forma de objeto el valor que asignamos a yield y la propiedad done que nos indica a través de true o false si el generador ya no tiene más valores que mostrar.

Veamos un ejemplo:

function *soyUnGenerador(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

var gen = soyUnGenerador(1);
console.log(gen.next());
//  Object {value: 2, done: false}
console.log(gen.next());
//  Object {value: 3, done: false}
console.log(gen.next());
//  Object {value: 4, done: false}
console.log(gen.next());
//  Object {value: undefined, done: true}

Cada vez que hemos llamado a next() ha entrado en la función y ha ejecutado una línea de las declaraciones de yield. Cuando ya no había más declaraciones, la función devuelve el valor undefined y el atributo done a false.

Esto puede ser utilizado para recursión, llamadas asíncronas, iteradores de arrays, etc..

En la documentación de Mozilla podemos ver un ejemplo de recursión con generadores con el número de Fibonacci:

function *fibonacci() { 
	let [anterior, actual] = [0, 1];
    for (;;) { 
    	[anterior, actual] = [actual, anterior + actual]; 
        yield actual; 
    }
}

let seq = fibonacci();
console.log(seq.next().value) // 1
console.log(seq.next().value) // 2
console.log(seq.next().value) // 3
console.log(seq.next().value) // 5
console.log(seq.next().value) // 8
...

Para complementar esto, comparto una charla sobre generadores que dió Sergio Arbeo en MadridJS hace ya un tiempecillo hablando de esto.

Imagen de cabecera: Modernweb

Carlos Azaustre

Carlos Azaustre

CTO y Cofundador de Chefly. Formador en tecnologías web: JavaScript, Node, Firebase, React y Vue.

Leer más