Що таке "функція *" в JavaScript?


243

На цій сторінці я знайшов новий тип функції 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;
    }
}

Я вже знаю , що yield, letі [?,?]=[?,?]робити , але не маю ні найменшого уявлення про те , що function*це має бути. Що це?

PS не заважайте пробувати Google, неможливо шукати вирази зірочками ( вони використовуються як заповнювачі ).


4
Коментар у прикладі зараз досить старий, function*синтаксис підтримується у Firefox з v26: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *. Старіші версії використовували інший синтаксис.
Миколай

39
Що стосується Google, просто шукайте "зірку функції" або "функцію зірочки". Ось як я знайшов це питання;).
трис

2
Схоже, це *було знято зі посилання від @Nickolay. Ось посилання безпосередньо function*на MDN . Звичайно, достатньо "базової" підтримки з v26 .
ruffin

Ще одне посилання MDN (яке, до речі, я знайшов на сторінці MDN, пов’язане ОП) : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
BlueRaja - Danny Pflughoeft

Ще одне корисне посилання MDN: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *
Логан

Відповіді:


199

Це функція генератора .

Генератори - це функції, які можна вийти та пізніше знову ввести. Їх контекст (змінні прив’язки) будуть збережені через повторні входи.

Виклик функції генератора не виконує його тіло відразу; замість цього повертається об’єкт ітератора для функції. Коли next()виклик методу ітератора, тіло функції генератора виконується до першого yieldвираження, яке визначає значення, яке потрібно повернути з ітератора, або yield*делегує іншій функції генератора.


Історична записка:

Це запропонований синтаксис для EcmaScript.next.

Дейв Герман з Mozilla розповів про EcmaScript.next . О 30:15 він розповідає про генератори.

Раніше він пояснює, як Mozilla експериментально впроваджує запропоновані зміни мови, щоб допомогти керувати комітетом. Дейв тісно співпрацює з Бренданом Айчем, CTO Mozilla (я думаю) та оригінальним дизайнером JavaScript.

Більш детальну інформацію можна знайти у вікі робочої групи EcmaScript: http://wiki.ecmascript.org/doku.php?id=harmony:generators

Робоча група (TC-39) має загальну згоду, що EcmaScript.next має мати якусь пропозицію ітератора генератора, але це не є остаточним.

Ви не повинні покладатися на це відображення без змін у наступній версії мови, і навіть якщо воно не зміниться, воно, певно, деякий час не відображатиметься в інших браузерах.

Огляд

Першокласні розробки, представлені у вигляді об'єктів, що інкапсулюють призупинені контексти виконання (тобто активації функції). Рівень мистецтва: Пітон, Ікона, Луа, Схема, Малий розмову.

Приклади

"Нескінченна" послідовність чисел Фібоначчі (незважаючи на поведінку близько 2 53 ):

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

Генератори можуть бути повторені в петлях:

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

Генератори - це ітератори:

let seq = fibonacci();
print(seq.next()); // 1
print(seq.next()); // 2
print(seq.next()); // 3
print(seq.next()); // 5
print(seq.next()); // 8

7
Слідкуйте: що робить цикл без параметрів ( for(;;))? Навіщо використовувати його в цьому контексті?
Фергі

13
@Fergie, for(;;)те саме, що while (true). Він використовується в цьому контексті, оскільки послідовність Фібоначчі є необмеженою послідовністю.
Майк Самуель

5
Попередній рівень техніки: вихід # C?
Дейв Ван ден Ейнде

3
@DaveVandenEynde, попередній рівень техніки: вихід Python. Попередній рівень техніки: CLU та Icon.
Майк Самуель

52

Це функція генератора - і це сказано на сторінці, яку ви цитуєте, у коментарі ви замінили на "це цікавий рядок" ...

В основному це спосіб задати послідовності програмно, щоб вони могли проходити навколо та елементи, доступ до яких здійснюється за допомогою індексу, без попереднього обчислення всієї послідовності (можливо, нескінченного розміру).


10
"Доступ за індексом без необхідності обчислювати всю послідовність", можливо, є найбільш корисним поясненням щодо генераторів, на які я стикався до цих пір. Я міг бачити, як використовувати це в додатку, порівняно раніше просто теоретично розуміючи це.
вс

11

У function*виглядає типу як він діє в якості опції генератора для процесів , які можуть бути ітерованих. C # має подібну функцію, використовуючи "прибуток", див. 1 та див. 2

По суті, це повертає кожне значення по одному до того, що повторює цю функцію, і саме тому їх використання показує це в циклі стилю foreach.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.