Programación en JavaScript/Generadores
Los generadores son parte de las especificaciones del estandar ECMAScript 6. Firefox soporta la sintaxis de los generadores de ECMAScript 6 desde el 10 de Octubre de 2013.[1] Node.js (Javascript server-side) también soporta la sintanxis para generadores.[2] desde el 15 de Mayo de 2013.
Uso
[editar]Los generadores pueden retornar uno o varios valores pausando su rutina sin terminarla. Además se les pueden pasar parámetros cada vez que se resume su rutina.[3]
La palabra clave yield
se podría interpretar como un return
que retorna un valor un estado cuando se llama al metodo next()
del generador. Para retornar un valor cuando se llama a next()
, en el código del generador se le debe colocar la expresión de retorno a la derecha de la palabra yield
. Por ejemplo: yield b;
primero retorna la variable b
y segundo pausa el flujo de ejecucion de la funcion a la espera de la proxima llamada a next()
.
La palabra clave yield
tambien se puede usar para recibir parámetros cada vez que se resume el flujo de ejecución de la función. Sólo se le debe pasar un parámetro a next(parametro)
, y en el código asignarle yield
a alguna variable o usar dicha palabra clave como parámetro de alguna función. Por ejemplo: var a = yield b;
primero retorna la variable b
, segundo pausa el flujo de ejecución de la función a la espera de la próxima llamada a next()
, y tercero (en la siguiente llamada a next()
) asigna el parámetro a la variable a
.
La palabra clave yield
siempre pausa el flujo de ejecución y retorna un valor, aunque se use para recibir un parametro. Cuando no se pasa un parametro, yield
asigna un undefined
. Cuando no se especifica un valor de retorno, yield
retorna un undefined
.
El metodo next()
siempre retorna un objeto con los atributos value
que es el valor retornado por yield
o por return
en un generador, y el atributo done
que con false
indica que el value
proviene de un yield
mientras que true
indica que proviene del return
. Una vez que se llega al return
, todas las demas llamadas a next()
devolveran un undefined
.[4][5]
Ejemplos
[editar]Un ejemplo simple con retorno con yield
y recepción de parámetros:
function* gen()
{
var a=0,b=undefined,c=0;
while(a<20)
{
if(b!=undefined)
{
a=b; // resetea la variuable "a" para que empiece desde el valor indicado como parametro en yield
c++; // suma un reset mas a la cantidad total hasta ahora
}
b=yield a+','+c; // retorna el valor de "a" concatenado con "c" y en el siguiente next()recibe un valor para "b"
a++;
}
return 'yield terminados. Esto es el return.';
}
var secuencia = gen();
secuencia.next(); // Object { value="0,0", done=false}
secuencia.next(); // Object { value="1,0", done=false}
secuencia.next(); // Object { value="2,0", done=false}
secuencia.next(10); // Object { value="10,1", done=false}
secuencia.next(); // Object { value="11,1", done=false}
secuencia.next(); // Object { value="12,1", done=false}
secuencia.next(5); // Object { value="5,2", done=false}
secuencia.next(); // Object { value="6,2", done=false}
secuencia.next(19); // Object { value="19,3", done=false}
secuencia.next(); // Object { value="20,3", done=false}
secuencia.next(); // Object { value="yield terminados. Esto es el return.", done=true}
La palabra clave function*
crea una función de tipo generador.
Cuando la palabra clave yield
se usa para retornar un valor y para asignar un valor, todo en la misma expresion, es importante tener en cuenta el orden en que se ejecutan ambas operaciones. Hay que tener en cuenta que cuando ambas operaciones estan en una misma expresion con yield
, siempre el retorno se ejecuta primero ante una llamada del metodo next()
y la asignacion despues en la siguiente llamada del metodo next()
. Esto es lógico, ya que que el flujo de ejecucion se pausa despues que yield
retorna un valor sin llegar a la asignacion. En la próxima llamada al metodo next()
se resume el flujo de ejecucion desde este punto, continuando con la asignacion y el resto de las instrucciones hasta el siguiente yield
o return
del generador.
Ejemplo dodne se puede ver la importancia del orden de ejecucición en una expresión con yield
:
function *crearGenerador() {
let primero = yield 1;
let segundo = yield primero + 2; // 4 + 2
yield segundo + 3; // 5 + 3
}
let generador = crearGenerador();
console.log(generador.next()); // "{ value: 1, done: false }"
console.log(generador.next(4)); // "{ value: 6, done: false }"
console.log(generador.next(5)); // "{ value: 8, done: false }"
console.log(generador.next()); // "{ value: undefined, done: true }"+
References
[editar]- ↑ "Firefox 26 for developers"
- ↑ "Does node.js support yield?"
- ↑ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
- ↑ http://gajus.com/blog/2/the-definitive-guide-to-the-javascript-generators
- ↑ https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Iterators_and_Generators