Qu'est-ce que la «fonction *» en JavaScript?

243

Dans cette page, j'ai trouvé un nouveau type de fonction 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;
    }
}

Je sais déjà ce que yield, letet [?,?]=[?,?]faire , mais ont aucune idée de ce que l' function*on entend être. Qu'Est-ce que c'est?

PS ne prend pas la peine d'essayer Google, il est impossible de rechercher des expressions avec des astérisques ( elles sont utilisées comme espaces réservés ).

chaîne QNA
la source
4
Le commentaire dans l'exemple est maintenant assez ancien, la function*syntaxe est prise en charge dans Firefox depuis la version 26: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *. Les versions plus anciennes utilisaient une syntaxe différente.
Nickolay
39
En ce qui concerne Google, recherchez simplement "fonction étoile" ou "fonction astérisque". C'est comme ça que j'ai trouvé cette question;).
trysis
2
On dirait que le a *été supprimé du lien de @Nickolay. Voici un lien directement vers function*MDN . Effectivement, support "basique" depuis la v26 .
ruffin
Un autre lien MDN (que, d'ailleurs, j'ai trouvé sur la page MDN liée par OP) : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
BlueRaja - Danny Pflughoeft

Réponses:

199

C'est une fonction de générateur .

Les générateurs sont des fonctions qui peuvent être fermées puis ré-entrées. Leur contexte (liaisons variables) sera enregistré à travers les rentrées.

L'appel d'une fonction de générateur n'exécute pas immédiatement son corps; un objet itérateur pour la fonction est renvoyé à la place. Lorsque la next()méthode de l'itérateur est appelée, le corps de la fonction de générateur est exécuté jusqu'à la première yieldexpression, qui spécifie la valeur à renvoyer de l'itérateur ou, avec yield*, délègue à une autre fonction de générateur.


Note historique:

C'est une syntaxe proposée pour EcmaScript.next.

Dave Herman de Mozilla a fait une présentation sur EcmaScript.next . A 30h15, il parle de générateurs.

Plus tôt, il explique comment Mozilla met en œuvre expérimentalement les changements de langue proposés pour aider à diriger le comité. Dave travaille en étroite collaboration avec Brendan Eich, CTO de Mozilla (je pense) et le concepteur JavaScript d'origine.

Vous pouvez trouver plus de détails sur le wiki du groupe de travail EcmaScript: http://wiki.ecmascript.org/doku.php?id=harmony:generators

Le groupe de travail (TC-39) est généralement d'accord sur le fait qu'EcmaScript.next devrait avoir une sorte de proposition d'itérateur de générateur, mais ce n'est pas définitif.

Vous ne devriez pas vous fier à ce que cela apparaisse sans modifications dans la prochaine version de la langue, et même si cela ne change pas, il n'apparaîtra probablement pas largement dans d'autres navigateurs pendant un certain temps.

Aperçu

Coroutines de première classe, représentées comme des objets encapsulant des contextes d'exécution suspendus (c'est-à-dire des activations de fonctions). Art antérieur: Python, Icon, Lua, Scheme, Smalltalk.

Exemples

La séquence «infinie» des nombres de Fibonacci (nonobstant le comportement autour de 2 53 ):

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

Les générateurs peuvent être répétés en boucles:

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

Les générateurs sont des itérateurs:

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
la source
7
Suivi: que fait une boucle for sans paramètres ( for(;;))? Pourquoi l'utiliser dans ce contexte?
Fergie
13
@Fergie, for(;;)c'est la même chose que while (true). Il est utilisé dans ce contexte car la séquence de Fibonacci est une séquence illimitée.
Mike Samuel
5
Art antérieur: rendement C #?
Dave Van den Eynde
3
@DaveVandenEynde, art antérieur: rendement Python. Art antérieur antérieur antérieur: CLU et Icon.
Mike Samuel
52

C'est une fonction de générateur - et cela est dit dans la page que vous citez, dans le commentaire que vous avez remplacé par "c'est la ligne intéressante" ...

Fondamentalement, c'est un moyen de spécifier des séquences par programme afin qu'elles puissent être transmises et les éléments accessibles par index sans avoir à calculer la séquence entière (éventuellement de taille infinie) au préalable.

Michael Borgwardt
la source
10
"accessible par index sans avoir à calculer la séquence entière" est peut-être l'explication la plus utile sur les générateurs que j'ai rencontrée jusqu'à présent. Je pourrais voir l'utilisation de cela dans une application, par rapport à la compréhension théorique antérieure.
wes
11

Le function*type semble agir comme une fonction de générateur pour les processus qui peuvent être itérés. C # a une fonctionnalité comme celle-ci en utilisant "rendement retour" voir 1 et voir 2

Essentiellement, cela renvoie chaque valeur une par une à ce qui itère cette fonction, c'est pourquoi leur cas d'utilisation la montre dans une boucle de style foreach.

Syntaxe invalide
la source