Co to jest „funkcja *” w JavaScript?

243

Na tej stronie znalazłem nowy typ funkcji 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;
    }
}

Już wiem co yield, leti [?,?]=[?,?]robić , ale nie mają pojęcia, co function*to miało być. Co to jest?

PS nie przeszkadza w wypróbowaniu Google, nie można wyszukiwać wyrażeń z gwiazdkami ( są one używane jako symbole zastępcze ).

ciąg QNA
źródło
4
Komentarz w tym przykładzie jest już dość stary, function*składnia jest obsługiwana w Firefox od wersji 26: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *. Starsze wersje używały innej składni.
Nickolay
39
Jeśli chodzi o Google, po prostu wyszukaj „gwiazdę funkcji” lub „gwiazdkę funkcji”. Tak znalazłem to pytanie;).
trysis
2
Wygląda na to, że *został usunięty z linku z @Nickolay. Oto link bezpośrednio do function*MDN . Oczywiście „podstawowa” obsługa od wersji 26 .
ruffin
Kolejny link MDN (który, nawiasem mówiąc, znalazłem na stronie MDN, do której prowadzi OP) : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
BlueRaja - Danny Pflughoeft

Odpowiedzi:

199

To funkcja generatora .

Generatory to funkcje, z których można wyjść, a następnie ponownie wprowadzić. Ich kontekst (powiązania zmienne) zostaną zapisane we wszystkich wejściach.

Wywołanie funkcji generatora nie powoduje natychmiastowego wykonania jej treści; zamiast tego zwracany jest obiekt iteratora dla funkcji. Po next()wywołaniu metody iteratora ciało funkcji generatora jest wykonywane do pierwszego yieldwyrażenia, które określa wartość, która ma zostać zwrócona z iteratora lub, za pomocą yield*, deleguje do innej funkcji generatora.


Nota historyczna:

Jest to proponowana składnia dla EcmaScript.next.

Dave Herman z Mozilli wygłosił wykład na temat EcmaScript.next . O 30:15 mówi o generatorach.

Wcześniej wyjaśnia, w jaki sposób Mozilla eksperymentalnie wdraża proponowane zmiany językowe, aby pomóc kierować komitetem. Dave ściśle współpracuje z Brendanem Eichem, CTO Mozilli (myślę) i oryginalnym projektantem JavaScript.

Więcej informacji można znaleźć na wiki grupy roboczej EcmaScript: http://wiki.ecmascript.org/doku.php?id=harmony:generators

Grupa robocza (TC-39) zgodziła się ogólnie, że EcmaScript.next powinien mieć jakąś propozycję iteratora generatora, ale to nie jest ostateczne.

Nie powinieneś polegać na tym, że będzie się wyświetlać bez zmian w następnej wersji języka, a nawet jeśli się nie zmieni, prawdopodobnie przez jakiś czas nie pojawi się szeroko w innych przeglądarkach.

Przegląd

Pierwszorzędne coroutines, reprezentowane jako obiekty otaczające zawieszone konteksty wykonania (tj. Aktywacje funkcji). Stan techniki: Python, Ikona, Lua, Schemat, Smalltalk.

Przykłady

„Nieskończona” sekwencja liczb Fibonacciego (niezależnie od zachowania około 2 53 ):

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

Generatory można iterować w pętlach:

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

Generatory są iteratorami:

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
źródło
7
Kontynuacja: co robi pętla for bez parametrów ( for(;;))? Dlaczego warto go używać w tym kontekście?
Fergie
13
@Fergie, for(;;)jest taki sam jak while (true). Jest używany w tym kontekście, ponieważ sekwencja Fibonacciego jest sekwencją nieograniczoną.
Mike Samuel
5
Stan techniki: Wydajność C #?
Dave Van den Eynde,
3
@DaveVandenEynde, stan techniki: Wydajność Python. Wcześniejszy stan techniki: CLU i ikona.
Mike Samuel,
52

Jest to funkcja generatora - i tak napisano na cytowanej stronie, w komentarzu zastąpionym przez „to jest ciekawa linia” ...

Zasadniczo jest to sposób programowego określania sekwencji, aby można było je przekazywać i uzyskiwać dostęp do elementów za pomocą indeksu bez konieczności wcześniejszego obliczania całej sekwencji (prawdopodobnie o nieskończonej wielkości).

Michael Borgwardt
źródło
10
„dostęp przez indeks bez konieczności obliczania całej sekwencji” jest prawdopodobnie najbardziej pomocnym wyjaśnieniem na temat generatorów, jakie do tej pory spotkałem. Widziałem użycie tego w aplikacji, a wcześniej tylko teoretyczne zrozumienie.
wes
11

Te function*spojrzenia typu jak to działa jako generator funkcji dla procesów, które można iterować. C # ma taką funkcję za pomocą „zwrotu z zysku” patrz 1 i patrz 2

Zasadniczo zwraca to każdą wartość jeden po drugim do tego, co iteruje tę funkcję, dlatego ich przypadek użycia pokazuje ją w pętli stylu foreach.

niepoprawna składnia
źródło