Ražība! Ražība! Kā ģeneratori darbojas JavaScript.

Ja nosaukums jau nedod mājienu, mēs šajā rakstā apspriedīsim ģeneratorus.

Pirms iedziļināšanās ģeneratoros pārskatīsim dažus pamatus par funkcijām.

  • JavaScript funkcijās ir teikumu kopums, kas veic uzdevumu un atgriež vērtību, kas beidzas ar funkciju.
  • Ja jūs atkal un atkal izsaucat funkciju, tā atkal un atkal izpildīs visus paziņojumus.
  • Bultas, kas reiz palikušas no priekšgala, nevar apturēt - tās tikai sit vai palaiž garām. Tādā pašā veidā funkciju, ko reiz izsauktu, nevar apturēt, tā darbosies, atgriezīs vērtību, metīs kļūdu un pēc tam apstāsies pēc visu paziņojumu izpildes.

Mums tikai jāpatur prātā šie 3 punkti, lai saprastu ģeneratorus.

Ģeneratori

Ģenerators ir īpašs funkcijas veids, kas var apturēt tā izpildi pusceļā un pēc kāda laika sākt no tā paša punkta. Ģeneratori ir funkciju un iteratoru kombinācija. Tas ir mazliet mulsinošs paziņojums, bet es pārliecināšos, ka raksta beigās šī rinda būs skaidra.

Skaidrības labad apsveriet iespēju spēlēt spēli, un pēkšņi mamma prasa kādu darbu. Jūs pārtraucat spēli, palīdzat viņai un pēc tam atsākat spēlēt. Līdzīgi ir ar ģeneratoriem.

Iteratora ir objekts, kas nosaka secību un, iespējams, atgriešanās vērtību līdz tā izbeigšanai. - MDN.

Iteratori paši par sevi ir milzīga tēma, un tie nav šī raksta mērķis.

Pamata sintakse

Ģeneratori tiek definēti kā funkcija ar zvaigznīti (*) blakus funkcijai.

function* name(arguments) { statements}

nosaukums - funkcijas nosaukums.

argumenti - Funkcijas argumenti.

paziņojumi - funkcijas ķermenis.

Atgriezties

Funkcija var atgriezt gandrīz visu, sākot no vērtības, objekta vai citas funkcijas. Ģeneratora funkcija atgriež īpašu objektu, ko sauc par ģeneratora objektu ( nav pilnīgi taisnība ). Objekts izskatās kā fragments zemāk

false

Objektam ir divas īpašības value un done. Vērtība satur iegūto vērtību . Gatavs sastāv no Būla (true | false), kas ģeneratoram saka, vai .next () dos vērtību vai nav definēts.

Iepriekš minēto apgalvojumu būs grūti sagremot. Mainīsim to ar piemēru.

function* generator(e) { yield e + 10; yield e + 25; yield e + 33;}var generate = generator(27);
console.log(generate.next().value); // 37console.log(generate.next().value); // 52console.log(generate.next().value); // 60console.log(generate.next().value); // undefined

Sapratīsim iepriekšminētā koda mehāniku pa rindām.

1. – 5. rinda: 1. – 5. rinda definē ģeneratoru ar tādu pašu nosaukumu ar argumentu e. Funkcijas pamattekstā tas satur virkni paziņojumu ar atslēgvārda ienesīgumu, un pēc tam tiek veikta kāda darbība.

6. līnija: 6. līnija piešķir ģeneratoru mainīgajam, ko sauc par ģeneratoru.

8. – 11. rinda: Šīs līnijas izsauc ķekaru noconsole.logkatra izsaucēja, kurš ir saistīts arnext metodi, kas prasavalueģeneratora objekta īpašību.

Ikreiz, kad tiek izmantota ģeneratora funkcija, atšķirībā no parastajām funkcijām tā netiek sākta uzreiz. Tā vietā tiek atgriezts iterators ( faktiskais iemesls * tiek izmantots ģeneratorā. Tas paziņo JS, ka ir jāatdod iteratora objekts ). Kad next()tiek izsaukta iteratora metode, ģeneratora izpilde sākas un tiek izpildīta, līdz tā atrod pirmo yield paziņojumu. Šajā ienesīguma brīdī tiek atgriezts ģeneratora objekts, kura specifikācijas jau ir izskaidrotas. Calling next()funkciju atkal atsāksies ģeneratora funkciju, līdz tā atrod citu yield paziņojumu, un cikls atgriežas līdz visi yields ir izsmelti.

Pēc šī punkta, ja next to sauc, tas atgriež ģeneratora objektu ar nenoteiktu vērtību.

Tagad mēģināsim iegūt citu ģeneratora funkciju no sākotnējā ģeneratora un arī atgriešanās paziņojumu.

returnPaziņojums ģeneratoram padarīs ģenerators pabeigt tās izpildi tāpat kā visi citi funkciju. done property No ģeneratora objekta tiks iestatīts true , un value atpakaļ tiks iestatīta value īpašuma ģeneratora objektu. Visi pārējie yields atgriezīsies undefined.

Ja tiek izmesta kļūda, tad arī ģeneratora darbība tiks pārtraukta, iegūstot pašu ģeneratoru.

Par yielding ģeneratoru mums ir nepieciešams, lai norādītu * pret yield , lai pateikt, JS, ka ģenerators ir iegūti. Par yield*deleģē citu ģeneratora funkciju - tas ir iemesls, kāpēc mēs varam yield visu vērtības generator2 funkcijas, izmantojot generate.next()sākotnējā ģeneratora funkciju. Pirmā vērtība yieldedir no pirmās ģeneratora funkcijas, un pēdējās divas yielded vērtības ģenerē ģeneratora funkcija, bet yielded sākotnējais ģenerators.

Priekšrocības

Slinks iekraušana

Slinkā slodze būtībā ir vērtības novērtēšana tikai tad, kad tā ir nepieciešama. Kā redzēsim nākamajā piemērā, mēs to faktiski varam izdarīt ar ģeneratoriem. Vērtības mēs varam iegūt tikai tad, kad nepieciešams, un ne visas vienlaikus.

Šis piemērs ir no cita šī raksta piemēra, un tas ģenerē bezgalīgus nejaušus skaitļus. Šeit mēs varam redzēt, ka varam piezvanīt tik daudz, next()cik vēlamies, un nesaņemt visas tās radītās vērtības. Tikai vajadzīgās.

function * randomize() { while (true) {let random = Math.floor(Math.random()*1000); yield random; }}
var random= randomize();
console.log(random.next().value)

Efektīva atmiņa

Kā mēs varam secināt no iepriekš minētā piemēra, ģeneratori ir ārkārtīgi efektīvi atmiņā. Tā kā mēs vēlamies vērtības tikai atbilstoši vajadzībām, šo vērtību glabāšanai mums ir nepieciešams daudz mazāk krātuves.

Kļūdas

Ģeneratori ir ļoti noderīgi, taču tiem ir arī savas nepilnības.

  • Ģeneratori nenodrošina nejaušu piekļuvi, piemēram, masīvus un citas datu struktūras. Tā kā pēc izsaukuma vērtības tiek iegūtas pa vienam, mēs nevaram piekļūt nejaušiem elementiem.
  • Ģeneratori nodrošina vienreizēju piekļuvi. Ģeneratori neļauj atkārtot vērtības atkārtoti. Kad visas vērtības ir izsmeltas, mums ir jāizveido jauns ģeneratora gadījums, lai atkal atkārtotu visas vērtības.

Kāpēc mums vajadzīgi ģeneratori?

Ģeneratori nodrošina plašu JavaScript izmantošanas veidu. Mēģināsim dažus atjaunot paši.

Iteratoru ieviešana

Iterators ir objekts, kas programmētājam ļauj šķērsot konteineru-Wikipedia

Mēs atkārtosim visus virknē esošos vārdus, izmantojot iteratorus. Arī stīgas ir atkārtotāji.

Iteratori

const string = 'abcde';const iterator = string[Symbol.iterator]();console.log(iterator.next().value)console.log(iterator.next().value)console.log(iterator.next().value)console.log(iterator.next().value)console.log(iterator.next().value)

Šeit ir tas pats, izmantojot ģeneratorus

function * iterator() {yield 'a';yield 'b';yield 'c';yield 'd';yield 'e';}for (let x of iterator()) {console.log(x);}

Salīdzinot abas metodes, ir viegli redzēt, ka ar ģeneratoru palīdzību mēs to varam izdarīt ar mazāku jucekli. Es zinu, ka tas nav ļoti labs piemērs, bet pietiek, lai pierādītu šādus aspektus:

  • Netiek ieviesta next()
  • No [Symbol.iterator]() invocation
  • In some cases, we even need to set the object.done property return value to true/false using iterators.

Async-Await ~ Promises+Generators

You can read my previous article about Async/Await if you want to learn about them, and check out this for Promises.

Crudely, Async/Await is just an implementation of Generators used with Promises.

Async-Await

async function async-await(){let a=await(task1);console.log(a);
let b=await(task2);console.log(b);
let c=await(task3);console.log(c);
}

Promises+Generators

function * generator-promise(){let a=yield Promise1();console.log(a);let b=yield Promise1();console.log(b);let c=yield Promise1();console.log(c);
}

As we can see, both produce the same result and almost in a similar fashion too. It’s because the Async/Await mechanism is loosely based on a combination of generators and promise. There is a lot more to Async/Await than shown above, but just for showing the use of a generator, we can consider this.

Infinite Data Structure

Virsraksts varētu būt nedaudz maldinošs, bet tā ir taisnība. Mēs varam izveidot ģeneratorus, izmantojot kādu laiku cilpu, kas nekad nebeigsies un vienmēr dos vērtību.

function * randomize() { while (true) {let random = Math.floor(Math.random()*1000); yield random; }}var random= randomize();while(true)console.log(random.next().value)

Iepriekš minētajā fragmentā mēs izveidojam bezgalīgu ģeneratoru, kas katram next() izsaukumam dos nejaušu skaitli . To var saukt par bezgalīgu nejaušu skaitļu plūsmu. Šis ir ļoti vienkāršs piemērs.

Secinājums

Par ģeneratoriem vēl ir daudz kas jāapskata, un tas bija tikai ievads tēmai. Ceru, ka uzzinājāt kaut ko jaunu, un raksts bija viegli saprotams.

Seko man un aplaudē!