¿Qué es "función *" en JavaScript?

243

En esta página encontré un nuevo tipo de función de JavaScript:

// NOTE: "function*" is not supported yet in Firefox.
// Remove the asterisk in order for this code to work in Firefox 13 

function* fibonacci() { // !!! this is the interesting line !!!
    let [prev, curr] = [0, 1];
    for (;;) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
    }
}

Ya sé qué yield, lety [?,?]=[?,?]hago , pero no tengo idea de lo function*que debe ser. ¿Qué es?

PD: no te molestes en probar Google, es imposible buscar expresiones con asteriscos ( se usan como marcadores de posición ).

string QNA
fuente
44
El comentario en el ejemplo es bastante antiguo ahora, la function*sintaxis es compatible con Firefox desde v26: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *. Las versiones anteriores usaban una sintaxis diferente.
Nickolay
39
Con respecto a Google, simplemente busque "función estrella" o "función asterisco". Así es como encontré esta pregunta;).
trysis
2
Parece que *fue eliminado del enlace de @Nickolay. Aquí hay un enlace directamente a function*MDN . Efectivamente, soporte "básico" desde v26 .
ruffin
Otro enlace MDN (que, por cierto, encontré en la página MDN vinculada por OP) : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
BlueRaja - Danny Pflughoeft

Respuestas:

199

Es una función de generador .

Los generadores son funciones que se pueden salir y luego volver a ingresar. Su contexto (enlaces variables) se guardará en las reentradas.

Llamar a una función generadora no ejecuta su cuerpo inmediatamente; en su lugar se devuelve un objeto iterador para la función. Cuando next()se llama al método del iterador , el cuerpo de la función del generador se ejecuta hasta la primera yieldexpresión, que especifica el valor que se devolverá del iterador o, con yield*, delega a otra función del generador.


Nota histórica:

Es una sintaxis propuesta para EcmaScript.next.

Dave Herman de Mozilla dio una charla sobre EcmaScript.next . A las 30:15 habla de generadores.

Anteriormente, explica cómo Mozilla está implementando experimentalmente los cambios de idioma propuestos para ayudar a dirigir el comité. Dave trabaja en estrecha colaboración con Brendan Eich, el CTO de Mozilla (creo), y el diseñador original de JavaScript.

Puede encontrar más detalles en el wiki del grupo de trabajo EcmaScript: http://wiki.ecmascript.org/doku.php?id=harmony:generators

El grupo de trabajo (TC-39) tiene un acuerdo general de que EcmaScript.next debería tener algún tipo de propuesta de iterador generador, pero esto no es definitivo.

No debe confiar en que aparezca sin cambios en la próxima versión del idioma, e incluso si no cambia, probablemente no se mostrará ampliamente en otros navegadores por un tiempo.

Visión general

Corutinas de primera clase, representadas como objetos que encapsulan contextos de ejecución suspendidos (es decir, activaciones de funciones). Técnica anterior: Python, Icon, Lua, Scheme, Smalltalk.

Ejemplos

La secuencia "infinita" de números de Fibonacci (a pesar del comportamiento alrededor de 2 53 ):

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

Los generadores se pueden iterar en bucles:

for (n of fibonacci()) {
    // truncate the sequence at 1000
    if (n > 1000)
        break;
    print(n);
}

Los generadores son iteradores:

let seq = fibonacci();
print(seq.next()); // 1
print(seq.next()); // 2
print(seq.next()); // 3
print(seq.next()); // 5
print(seq.next()); // 8
Mike Samuel
fuente
77
Seguimiento: ¿qué hace un bucle for sin parámetros ( for(;;))? ¿Por qué usarlo en este contexto?
Fergie
13
@Fergie, for(;;)es lo mismo que while (true). Se usa en este contexto ya que la secuencia de Fibonacci es una secuencia ilimitada.
Mike Samuel
55
Técnica anterior: ¿rendimiento de C #?
Dave Van den Eynde
3
@DaveVandenEynde, estado de la técnica anterior: rendimiento de Python. Técnica anterior anterior anterior: CLU e icono.
Mike Samuel
52

Es una función generadora , y así lo dijo en la página que cita, en el comentario que reemplazó con "esta es la línea interesante" ...

Básicamente es una forma de especificar secuencias mediante programación para que puedan pasarse y acceder a los elementos por índice sin tener que calcular la secuencia completa (posiblemente de tamaño infinito) de antemano.

Michael Borgwardt
fuente
10
"Acceso por índice sin tener que calcular toda la secuencia" es posiblemente la explicación más útil sobre los generadores que he encontrado hasta ahora. Pude ver el uso de esto en una aplicación, en comparación con la comprensión anterior teóricamente.
wes
11

Los function*de tipo parece que actúa como un generador de función para los procesos que se pueden repetir. C # tiene una característica como esta usando "rendimiento de rendimiento", ver 1 y ver 2

Esencialmente, esto devuelve cada valor uno por uno a lo que sea que esté iterando esta función, por lo que su caso de uso lo muestra en un bucle de estilo foreach.

sintaxis inválida
fuente