JavaScript'te “function *” nedir?


243

Gelen bu sayfada yeni bir JavaScript işlevi türü bulundu:

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

Zaten bildiğim ne yield, letve [?,?]=[?,?]bunu ancak hiç bir fikrim yok function*olması gerekiyordu. Bu ne?

PS, Google'ı denemeyi rahatsız etmiyor , yıldız işaretli ifadeleri aramak imkansız ( yer tutucu olarak kullanılıyorlar ).


4
Örnekteki yorum şu anda oldukça eski, function*sözdizimi v26'dan beri Firefox'ta destekleniyor: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *. Eski sürümlerde farklı bir sözdizimi kullanılmıştır.
Nickolay

39
Google ile ilgili olarak, "işlev yıldızı" veya "işlev yıldız" ı arayın. Bu soruyu bu şekilde buldum;).
trysis

2
*@Nickolay bağlantısından soyulmuş gibi görünüyor . İşte doğrudan function*MDN'de bir bağlantı . Tabii ki v26 beri "temel" destek .
ruffin

Başka bir MDN bağlantısı (bu arada, OP tarafından bağlantılı MDN sayfasında buldum) : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
BlueRaja - Danny Pflughoeft

Başka bir yararlı MDN bağlantısı: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… *
Logan

Yanıtlar:


199

Bu bir Jeneratör fonksiyonudur.

Jeneratörler çıkılabilen ve daha sonra tekrar girilebilen fonksiyonlardır. Bağlamları (değişken bağlamalar) tüm girişlerde kaydedilecektir.

Bir jeneratör fonksiyonunun çağrılması derhal vücudunu yürütmez; bunun yerine işlev için bir yineleyici nesnesi döndürülür. Yineleyicinext() yöntemi çağrıldığında, üreteç işlevinin gövdesi, yieldyineleyiciden döndürülecek değeri belirten ilk ifadeye kadar veya yield*başka bir üreteç işlevine temsilci atanıncaya kadar yürütülür .


Tarihsel not:

İçin önerilen bir sözdizimi EcmaScript.next.

Mozilla'dan Dave Herman hakkında bir konuşma yaptı EcmaScript.next . 30: 15'te jeneratörlerden bahsediyor.

Daha önce, Mozilla'nın komiteyi yönlendirmek için önerilen dil değişikliklerini deneysel olarak nasıl uyguladığını açıklıyor. Dave, Mozilla'nın CTO'su Brendan Eich ve orijinal JavaScript tasarımcısı ile yakın bir şekilde çalışıyor.

EcmaScript çalışma grubu wiki'si hakkında daha fazla bilgi bulabilirsiniz: http://wiki.ecmascript.org/doku.php?id=harmony:generators

Çalışma grubu (TC-39), EcmaScript.next dosyasının bir tür jeneratör yineleyici teklifine sahip olması gerektiği konusunda genel bir anlaşmaya sahiptir, ancak bu nihai değildir.

Dilin bir sonraki sürümünde değişiklik yapmadan bu gösterime güvenmemelisiniz ve değişmese bile, muhtemelen bir süre diğer tarayıcılarda yaygın olarak görünmeyecektir.

genel bakış

Askıya alınmış yürütme bağlamlarını (yani, işlev aktivasyonlarını) kapsayan nesneler olarak temsil edilen birinci sınıf couteinler. Önceki sanat: Python, İkon, Lua, Şema, Smalltalk.

Örnekler

Fibonacci sayılarının “sonsuz” dizisi (2 53 civarındaki davranışa rağmen ):

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

Jeneratörler döngüler halinde tekrarlanabilir:

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

Jeneratörler yineleyicilerdir:

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

7
Takip: parametresiz bir for döngüsü ( for(;;)) ne yapar? Neden bu bağlamda kullanılıyor?
Fergie

13
@Fergie, for(;;)ile aynı while (true). Bu bağlamda Fibonacci dizisi sınırsız bir dizi olduğu için kullanılır.
Mike Samuel

5
Önceki teknik: C # verimi?
Dave Van den Eynde

3
@DaveVandenEynde, önceki teknik: Python verimi. Önceki önceki teknik: CLU ve Icon.
Mike Samuel

52

Bu bir jeneratör işlevi - ve belirttiğiniz sayfada, "ilginç çizgi bu" ile değiştirdiğiniz yorumda öyle dedi ...

Temel olarak, dizileri programsal olarak belirtmenin bir yoludur, böylece tüm diziyi (muhtemelen sonsuz boyutta) önceden hesaplamak zorunda kalmadan dizinden ve dizin tarafından erişilebilen öğelerden geçilebilir.


10
"tüm diziyi hesaplamak zorunda kalmadan dizin tarafından erişildi" muhtemelen şimdiye kadar karşılaştığım jeneratörler hakkında en yararlı açıklama parçasıdır. Bunu daha önce sadece teorik olarak anlamak vs, bir app kullanarak görebiliyordu.
wes

11

function*Tip görünüyor o iterated işlemleri için bir jeneratör işlevi olarak görür gibi. C #, "verim geri dönüşü" için bkz. 1 ve 2'yi kullanarak böyle bir özelliğe sahiptir.

Temel olarak bu, bu işlevi yineleyen her değere birer birer döner, bu nedenle kullanım durumları bunu bir foreach stil döngüsünde gösterir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.