javascript - Kan jeg bruke ES6 sin pilfunksjonssyntaks med generatorer? (pilnotasjon)


Det vil si, hvordan uttrykker jeg

function *(next) {}

med pil-syntaks? Jeg har prøvd alle kombinasjonene jeg kunne tenke meg, og jeg kan ikke finne noen dokumentasjon på det.

(Jeg bruker for øyeblikket Node.js v0.11.14.)

Svar #1

Kan jeg bruke ES6s pilfunksjonssyntaks med generatorer?

Du kan ikke. Beklager.

Ifølge MDN

function*-setningen (function-nøkkelordet etterfulgt av en stjerne) definerer en generatorfunksjon.

Fra et spesifikasjonsdokument (min utheving):

Syntaksen for funksjon er utvidet for å legge til en valgfri *-token:

FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")" 
  "{" FunctionBody "}"

Svar #2

Forskjellen mellom inline-funksjoner og pilfunksjoner

Først og fremst er ikke Arrow-funksjoner () => {} laget for å erstatte Inline-funksjoner function(){}, og de er forskjellige. Inline-funksjoner er rett og slett funksjoner, så spørsmålet er hva forskjellen mellom Arrow-funksjoner og Inline-funksjoner er.

Et pilfunksjonsuttrykk (også kjent som pilfunksjon) har en kortere syntaks sammenlignet med funksjonsuttrykk og binder ikke sin egen this, arguments, super eller new.target. Pilfunksjoner er alltid anonyme.

Noen flere raske detaljer her


Hvorfor pilfunksjon ikke kan brukes som generatorer

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Bruk av yield-nøkkelordet

Nøkkelordet yield kan ikke brukes i kroppen til en pilfunksjon (bortsett fra når det er tillatt innen funksjoner som er ytterligere nestet inne i den). Som en konsekvens kan ikke pilfunksjoner brukes som generatorer.

Merk at generatorer uten yield ikke gir mening.


Hvorfor kan ikke pilfunksjon bruke yield

http://tc39wiki.calculist.org/es6/arrow-functions/

Pilfunksjoner binder this leksikalt, binder return i Block-kroppstilfellene slik at det returnerer fra den umiddelbart innkapslede pilfunksjonen, og hindrer break og continue fra å referere til setninger utenfor den umiddelbart innkapslede pilfunksjonen.

Den Identifier primære uttrykket arguments kan ikke brukes i kroppen til en pilfunksjon (enten som uttrykk eller blokkform).

På samme måte kan yield ikke brukes i en pilfunksjons kropp. Piler kan ikke være generatorer, og vi ønsker ikke dype fortsettelser.

Yield i en pilfunksjon vil kaste semantisk feil: http://www.ecma-international.org/

Til slutt ligger årsaken i den dype kompleksiteten i implementeringen av ECMA6. C# tillater heller ikke dette av noe lignende grunner.

Svar #3

I tillegg til diskusjonen på esdiscuss.org og Ecma TC39-komiteens ES6-møteprotokoller fra november 2013 nevnt ovenfor, ble generator-piler tatt opp igjen i to ES7-møter i september 2016 [1] [2]. Etter en diskusjon om fordeler og ulemper ved ulike syntakser (hovedsakelig =*> og =>*) og en mangel på begrunnelser og brukstilfeller for denne funksjonen, kom de til følgende konklusjon:

  • Det er en viss interesse fra komiteen, men bekymring for at funksjonen ikke gjør sin del for å legge til en ny syntaksdel
  • Planlegg å komme tilbake på dag 3 for å se om vi kan få =>* til minst nivå 0, som en del av [Domenic Denicolas] forslag om asynkron iterasjon

Forslaget om generatorpiler ble flyttet til Trinn 1 med Brendan Eich og Domenic Denicola som forkjempere. Asynkron iterasjon nevnt ovenfor ble fullført og implementert i 2018.

I oktober 2019 dukket det opp et offisielt repo av Sergey Rubanov med mer diskusjon om syntaks og andre detaljer.

Svar #4

Akkurat nå kan du ikke, men i fremtiden kan det hende du kan fordi TC39 ga ut et forslag for det samme i oktober 2019, som er i fase 1.

Svar #5

Jeg hadde også det samme spørsmålet og kom hit. Etter å ha lest innleggene og kommentarene, følte jeg at det å bruke generator i en pilfunksjon virker uklart:

const generator = () => 2*3; // * implies multiplication
// so, this would be a confusing
const generator = () =>* something; // err, multiplying?
const generator = () =*> ... // err, ^^
const generator = ()*=> ... // err, *=3, still multiplying?
const generator=*()=> ... // err, ^^
const generator = *param => ... //err, "param" is not fixed word

Dette er kanskje den store grunnen til at de ikke implementerte generator i forhold til pilfunksjon.

Men hvis jeg var en av dem, kunne jeg ha tenkt slik:

const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^

Dette føles akkurat som om vi har en asynkron funksjon:

const asyncFunction = async () => ... // pretty cool

Fordi, med normal funksjon eksisterer async-nøkkelordet, så pilfunksjonen utnytter det - async() => vil sannsynligvis se ut som async function().

Men det finnes ingen nøkkelord som gen eller generator, og dessverre bruker ikke pilfunksjonen det.

For å konkludere:

Selv om de ønsker å implementere generatoren i pilfunksjonen, tror jeg de trenger å tenke på nytt om generatorsyntaksen i kjerne-js:

generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}

Og dette vil være en stor tabbe. Så å holde pilfunksjonen utenfor generatoren er ganske kult.

Følgende @Bergi kommentar:

Nei. Arrow-funksjoner skal være lettvekts (og har for eksempel ikke .prototype) og ofte enlinjede, mens generatorer er nærmest det motsatte.

Jeg vil si at generatorens formål å bruke er kjør-stopp-kjør og derfor tror jeg ikke vi trenger å bry oss om prototype, leksikalsk this, osv.

Relaterte artikler