javascript - paso - ¿Dónde va el argumento de la primera llamada siguiente()?
pasar parametros a javascript (2)
El next
método se define de la siguiente manera:
25.3.1.2 Generator.prototype.next (valor)
El
next
método realiza los siguientes pasos:
- Deje que g sea este valor.
- Return GeneratorResume ( g , value ).
La operación abstracta GeneratorResume usa valor en el paso 10:
25.3.3.3 GeneratorResume (generador, valor)
La operación abstracta GeneratorResume con argumentos generador y valor realiza los siguientes pasos:
- Deje genContext ser el valor de la ranura interna del generador [[GeneratorContext]].
- Reanude la evaluación suspendida de genContext usando NormalCompletion ( valor ) como resultado de la operación que lo suspendió . Deje que el resultado sea el valor devuelto por el cálculo reanudado.
La primera posibilidad es que las evaluaciones se suspendieron mediante el uso del yield
(es decir, el estado "suspendedYield"
).
Su comportamiento se explica en 14.4.14 Semántica de tiempo de ejecución: Evaluación :
YieldExpression :
yield
- Return GeneratorYield ( CreateIterResultObject ( undefined , false )).
(Análogo para YieldExpression : yield
AssignmentExpression )
La operación abstracta GeneratorYield suspende el generador de la siguiente manera:
Establezca el estado de evaluación del código de genContext de manera que cuando la evaluación se reanude con un Completion ResumptionValue se lleven a cabo los siguientes pasos:
- Return reanudationValue .
- NOTA: Esto vuelve a la evaluación de la producción YieldExpression que originalmente llamó a esta operación abstracta.
Por lo tanto, el valor pasado como el argumento del segundo next
se usa como el valor devuelto de la primera expresión de yield
. Y el valor pasado como el argumento del 3er next
se usa como el valor devuelto de la 2da expresión de yield
. Y así.
Sin embargo, también existe la posibilidad de que el generador no haya comenzado todavía (es decir, el estado "suspendedStart"
).
Esto se hace mediante la operación abstracta GeneratorStart :
- Establezca el estado de evaluación del código de genContext de modo que cuando se reanude la evaluación para ese contexto de ejecución , se realicen los siguientes pasos:
Pero esos "siguientes pasos" no usan el valor de reanudación.
Por lo tanto, el valor pasado como el argumento de la primera next
se descarta.
Esta pregunta ya tiene una respuesta aquí:
Tengo una función de generador simple
function *generate(arg) {
console.log(arg)
for(let i = 0; i < 3;i++) {
console.log(yield i);
}
}
Luego, inicio el generador y trato de imprimir valores en la consola:
var gen = generate(''arg''); //doesn''t print
gen.next(''a''); // prints ''arg''
gen.next(''b''); // prints ''b''
gen.next(''c''); // prints ''c''
// ... nothing surprising later
¿De dónde salió el argumento a
de la primera llamada next()
? ¿Hay alguna forma de utilizarlo dentro de la función del generador?
Aquí hay un Babel REPL donde puedes ver ese resultado.
No, no puedes usar ese primer valor. Es instructivo si cambias tu código a:
''use strict'';
function *generate(arg) {
console.log(arg)
for(let i = 0; i < 3;i++) {
console.log(yield i);
}
return ''done'';
}
var gen = generate(''arg'');
console.log(gen.next(''a''));
console.log(gen.next(''b''));
console.log(gen.next(''c''));
console.log(gen.next(''d''));
Cuando crea una instancia del generador, no comienza a ejecutarse aún y no se registra nada. En el primer gen.next(''a'')
, se ejecuta hasta el primer rendimiento que pasa por console.log(arg)
en el generador y luego yield 0
. Esto luego obtiene console.log
en la persona que llama y obtiene {value: 0, done:false}
, etc. hasta que complete la iteración. El resultado general se ve de la siguiente manera:
arg
{ value: 0, done: false }
b
{ value: 1, done: false }
c
{ value: 2, done: false }
d
{ value: ''done'', done: true }
El resultado final es el valor de retorno y no estará undefined
si omite el return
en el generador.