web-dev-qa-db-fra.com

À quoi sert un astérisque (*) dans les fonctions du générateur ES6

Quelqu'un peut-il m'expliquer: pourquoi les fonctions du générateur dans ES6 sont-elles marquées par un astérisque?

Par exemple, au lieu de:

function *someGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

on pourrait écrire:

function someGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

ou même:

var someGenerator = () => {
    yield 1;
    yield 2;
    yield 3;
}

var someObject = {

    someGenerator() {
        yield 1;
        yield 2;
        yield 3;
    }
}            

Le compilateur JS peut détecter que someGenerator contient l'opérateur yield au moment de l'analyse et créer un générateur à partir de cette fonction.

Pourquoi la détection de l'existence de yield n'est-elle pas suffisante?

43
alexpods

Les trois raisons étaient les suivantes:

  1. lisibilité. Un générateur est assez différent d'une fonction, et la différence doit être immédiatement visible (c'est-à-dire sans examiner toute l'implémentation à la recherche d'un rendement).

  2. Généralités. Il devrait être naturellement possible d'écrire des générateurs qui ne cèdent pas et ne retournent que directement. De plus, commenter une partie du corps (par exemple pour le débogage) ne devrait pas changer silencieusement si quelque chose est un générateur.

  3. Compatibilité. Seul le mode strict réservait le "rendement" comme mot clé, mais l'objectif d'ES6 était que toutes les nouvelles fonctionnalités soient également disponibles en mode bâclé (une décision malheureuse à mon humble avis, mais néanmoins). De plus, même en mode strict, il existe de nombreuses subtilités d'analyse autour du "rendement"; par exemple, considérez les arguments par défaut:

    function* g(a = yield(2)) { 'use strict' }
    

    Sans le *, l'analyseur ne peut décider comment analyser le rendement qu'après avoir vu le corps de la fonction. C'est-à-dire que vous auriez besoin d'une anticipation infinie, d'un suivi arrière ou d'autres techniques de piratage pour y faire face.

Je dois noter que (1) et (2) sont déjà une raison suffisante.

(Divulgation complète: je suis membre du comité EcmaScript.)

55
Andreas Rossberg

Les générateurs vides (sans corps) ne sont pas interdits; donc unStarredFunc() doit-il suivre la sémantique du générateur ou non?

Pour des raisons de compatibilité:

function yield(x) { return x };

function a() { 
    yield (4+1);
};

ceci est syntaxiquement correct mais appeler .next() entraînerait une erreur alors que l'ajout d'un astérisque pour définir explicitement un générateur entraînerait .next().value === 5

détecter que someGenerator contient un opérateur de rendement au moment de l'analyse

Certaines constructions ne peuvent pas être résolues au moment de l'analyse:

function someGenerator(i) { 
    if (glob) 
        return 4; 
    else 
        yield* anotherGen(i);
}

Et bien sûr, il est plus simple de voir immédiatement à partir de la définition function* Que c'est un générateur sans avoir besoin de creuser dans sa source pour rechercher des rendements.

7
Alex K.