javascript - generadores - ¿Cuál es el propósito de un asterisco(*) en las funciones del generador ES6?
yield javascript (2)
Las tres razones fueron:
Legibilidad Un generador es bastante diferente de una función, y la diferencia debe ser inmediatamente visible (es decir, sin examinar toda la implementación en busca de un rendimiento).
Generalidad Naturalmente, debería ser posible escribir generadores que no rindan y que solo regresen directamente. Además, comentar una parte del cuerpo (por ejemplo, para la depuración) no debe cambiar silenciosamente si algo es un generador.
Compatibilidad Solo el modo estricto reservó "rendimiento" como palabra clave, pero se convirtió en un objetivo para ES6 que todas las funciones nuevas también estén disponibles en modo descuidado (una desafortunada decisión en mi humilde opinión, pero de todos modos). Además, incluso en modo estricto, hay muchas sutilezas de análisis en torno al "rendimiento"; por ejemplo, considere los argumentos predeterminados:
function* g(a = yield(2)) { ''use strict'' }
Sin
*
, el analizador solo podía decidir cómo analizar el rendimiento una vez que ha visto el cuerpo de la función. Es decir, necesitaría una mirada infinita, un seguimiento posterior u otras técnicas hacky para lidiar con esto.
Debo señalar que (1) y (2) ya son motivo suficiente.
(Divulgación completa: soy un miembro del comité de EcmaScript.)
¿Puede alguien explicarme por qué las funciones del generador en ES6 están marcadas con un símbolo de asterisco?
Por ejemplo, en lugar de:
function *someGenerator() {
yield 1;
yield 2;
yield 3;
}
podríamos escribir:
function someGenerator() {
yield 1;
yield 2;
yield 3;
}
o incluso:
var someGenerator = () => {
yield 1;
yield 2;
yield 3;
}
var someObject = {
someGenerator() {
yield 1;
yield 2;
yield 3;
}
}
El compilador JS puede detectar que someGenerator
contiene el operador de yield
en el tiempo de análisis y someGenerator
un generador a partir de esta función.
¿Por qué la detección de yield
no es suficiente?
Los generadores vacíos (sin cuerpo) no están prohibidos; entonces, ¿debería unStarredFunc()
seguir la semántica del generador o no?
Por razones de compatibilidad:
function yield(x) { return x };
function a() {
yield (4+1);
};
esto es sintácticamente correcto, pero llamar a .next()
daría como resultado un error, mientras que agregar un asterisco para definir explícitamente un generador provocaría .next().value === 5
detectar que someGenerator contiene el operador de rendimiento en el tiempo de análisis
Algunos constructos no se pueden resolver en el tiempo de análisis:
function someGenerator(i) {
if (glob)
return 4;
else
yield* anotherGen(i);
}
Y, por supuesto, es más fácil ver de inmediato la definición de function*
que es un generador sin necesidad de profundizar en su fuente para buscar rendimientos.