Apa itu "fungsi *" dalam JavaScript?

243

Di halaman ini saya menemukan tipe fungsi JavaScript baru:

// 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;
    }
}

Saya sudah tahu apa yield, letdan [?,?]=[?,?]melakukan , tetapi tidak tahu apa yang function*dimaksudkan. Apa itu?

PS jangan repot-repot mencoba Google, tidak mungkin untuk mencari ekspresi dengan tanda bintang ( mereka digunakan sebagai pengganti ).

string QNA
sumber
4
Komentar dalam contoh sudah cukup tua sekarang, function*sintaks didukung di Firefox sejak v26: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *. Versi yang lebih lama menggunakan sintaks yang berbeda.
Nickolay
39
Mengenai Google, cari saja "function star" atau "function asterisk". Begitulah cara saya menemukan pertanyaan ini;).
trysis
2
Sepertinya *itu dihapus dari tautan dari @Nickolay. Berikut ini tautan langsung ke function*di MDN . Benar saja, dukungan "dasar" sejak v26 .
ruffin
Tautan MDN lain (yang, omong-omong, saya temukan di laman MDN yang ditautkan oleh OP) : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
BlueRaja - Danny Pflughoeft
Tautan MDN lain yang bermanfaat: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *
Logan

Jawaban:

199

Ini adalah fungsi Generator .

Generator adalah fungsi yang dapat keluar dan kemudian dimasukkan kembali. Konteks mereka (binding variabel) akan disimpan di seluruh pintu masuk.

Memanggil fungsi generator tidak menjalankan tubuhnya dengan segera; objek iterator untuk fungsi dikembalikan sebagai gantinya. Ketika metode iterator next()dipanggil, fungsi fungsi generator dijalankan sampai yieldekspresi pertama , yang menentukan nilai yang akan dikembalikan dari iterator atau, dengan yield*, mendelegasikan ke fungsi generator lain.


Catatan sejarah:

Ini sintaks yang diusulkan untuk EcmaScript.next.

Dave Herman dari Mozilla memberi ceramah tentang EcmaScript.next . Pada 30:15 ia berbicara tentang generator.

Sebelumnya, dia menjelaskan bagaimana Mozilla secara eksperimental menerapkan perubahan bahasa yang diusulkan untuk membantu mengarahkan komite. Dave bekerja sama dengan Brendan Eich, CTO Mozilla (saya pikir), dan perancang JavaScript asli.

Anda dapat menemukan lebih detail tentang wiki kelompok kerja EcmaScript: http://wiki.ecmascript.org/doku.php?id=harmony:generators

Kelompok kerja (TC-39) memiliki persetujuan umum bahwa EcmaScript.next harus memiliki semacam proposal generator iterator, tetapi ini belum final.

Anda tidak boleh mengandalkan ini muncul tanpa perubahan dalam versi bahasa berikutnya, dan bahkan jika itu tidak berubah, itu mungkin tidak akan muncul secara luas di browser lain untuk sementara waktu.

Gambaran

Coroutine kelas satu, direpresentasikan sebagai objek yang mengenkapsulasi konteks eksekusi yang ditangguhkan (yaitu, aktivasi fungsi). Seni sebelumnya: Python, Ikon, Lua, Skema, Smalltalk.

Contohnya

Urutan "tak terbatas" dari angka-angka Fibonacci (meskipun perilaku sekitar 2 53 ):

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

Generator dapat diulang dalam loop:

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

Generator adalah iterator:

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
sumber
7
Tindak lanjut: apa yang dilakukan untuk loop tanpa parameter ( for(;;)) lakukan? Mengapa menggunakannya dalam konteks ini?
Fergie
13
@ Fergie, for(;;)sama dengan while (true). Ini digunakan dalam konteks ini karena urutan Fibonacci adalah urutan tanpa batas.
Mike Samuel
5
Seni sebelumnya: C # yield?
Dave Van den Eynde
3
@DaveVandenEynde, prior art sebelumnya: Python yield. Prior prior prior prior: CLU dan Icon.
Mike Samuel
52

Ini adalah fungsi generator - dan dikatakan demikian di halaman yang Anda kutip, dalam komentar yang Anda ganti dengan "ini adalah baris yang menarik" ...

Pada dasarnya ini adalah cara untuk menentukan urutan secara terprogram sehingga mereka dapat diedarkan dan elemen diakses oleh indeks tanpa harus menghitung seluruh urutan (ukuran mungkin tak terbatas) sebelumnya.

Michael Borgwardt
sumber
10
"diakses oleh indeks tanpa harus menghitung seluruh urutan" mungkin adalah penjelasan yang paling membantu tentang generator yang saya temui sejauh ini. Saya bisa melihat menggunakan ini dalam aplikasi, vs sebelumnya hanya memahaminya secara teoritis.
wes
11

The function*jenis terlihat seperti itu bertindak sebagai fungsi generator untuk proses yang dapat mengulangi. C # memiliki fitur seperti ini menggunakan "hasil pengembalian" lihat 1 dan lihat 2

Pada dasarnya ini mengembalikan setiap nilai satu per satu ke apa pun yang mengulangi fungsi ini, itulah sebabnya kasus penggunaannya menunjukkannya dalam loop gaya foreach.

sintaks tidak valid
sumber