Bralci, kot ste vi, pomagajo podpirati MUO. Ko opravite nakup prek povezav na našem spletnem mestu, lahko zaslužimo partnersko provizijo. Preberi več.

Ponavljanje zbirk podatkov z uporabo tradicionalnih zank lahko hitro postane okorno in počasno, še posebej, če imate opravka z ogromnimi količinami podatkov.

Generatorji in iteratorji JavaScript nudijo rešitev za učinkovito ponavljanje velikih zbirk podatkov. Z njihovo uporabo lahko nadzirate tok iteracije, pridobite vrednosti eno za drugo ter zaustavite in nadaljujete postopek iteracije.

Tukaj boste obravnavali osnove in notranjost iteratorja JavaScript ter kako lahko ročno in z generatorjem ustvarite iterator.

Iteratorji JavaScript

Iterator je objekt JavaScript, ki implementira protokol iteratorja. Ti predmeti to storijo tako, da imajo a Naslednji metoda. Ta metoda vrne objekt, ki implementira IteratorResult vmesnik.

The IteratorResult vmesnik vsebuje dve lastnosti: Končano in vrednost. The Končano lastnost je logična vrednost, ki vrne lažno

instagram viewer
če lahko iterator proizvede naslednjo vrednost v svojem zaporedju oz prav če je iterator zaključil svoje zaporedje.

The vrednost Lastnost je vrednost JavaScript, ki jo vrne iterator med svojim zaporedjem. Ko iterator zaključi svoje zaporedje (ko Končanoprav), se ta lastnost vrne nedoločeno.

Kot pove že ime, vam iteratorji omogočajo "iteracijo" po objektih JavaScript, kot so polja ali zemljevidi. To vedenje je možno zaradi ponovljivega protokola.

V JavaScriptu je iterable protokol standardni način definiranja predmetov, ki jih lahko ponavljate, na primer v za...od zanka.

Na primer:

konst sadje = ["banana", "Mango", "jabolko", "Grozdje"];

za (konst iterator od sadje) {
konzola.log (iterator);
}

/*
Banana
Mango
Apple
grozdje
*/

Ta primer ponavlja čez sadje niz z uporabo a za...od zanka. V vsaki ponovitvi zapiše trenutno vrednost v konzolo. To je mogoče, ker so polja ponovljiva.

Nekatere vrste JavaScript, kot so polja, nizi, Kompleti in zemljevidiso vgrajene iterable, ker (ali eden od objektov v njihovi prototipni verigi) izvajajo @@iterator metoda.

Drugih tipov, kot so predmeti, privzeto ni mogoče ponoviti.

Na primer:

konst iterObject = {
avtomobili: ["Tesla", "BMW", "Toyota"],
živali: ["Mačka", "pes", "Hrček"],
hrano: ["Burgerji", "pica", "testenine"],
};

za (konst iterator od iterObject) {
konzola.log (iterator);
}

// TypeError: iterObject ni mogoče ponoviti

Ta primer prikazuje, kaj se zgodi, ko poskušate ponoviti objekt, ki ga ni mogoče ponoviti.

Izdelava predmeta, ki ga je mogoče ponoviti

Če želite narediti objekt ponovljiv, morate implementirati a Simbol.iterator metodo na objektu. Da postane ponovljiva, mora ta metoda vrniti objekt, ki implementira IteratorResult vmesnik.

The Simbol.iterator simbol služi istemu namenu kot @@iterator in se lahko uporablja zamenljivo v "specifikaciji", ne pa tudi v kodi kot @@iterator ni veljavna sintaksa JavaScript.

Spodnji bloki kode nudijo primer, kako narediti predmet, ki ga je mogoče ponoviti z uporabo iterObject.

Najprej dodajte Simbol.iterator način za iterObject uporabo funkcijo izjava.

takole:

iterObject[Simbol.iterator] = funkcijo () {
// Naslednji bloki kode gredo sem ...
}

Nato boste morali dostopati do vseh ključev v objektu, ki ga želite narediti ponovljivega. Do tipk lahko dostopate z Object.keys metoda, ki vrne matriko naštevnih lastnosti predmeta. Če želite vrniti niz iterObject’s keys, pass the to ključna beseda kot argument za Object.keys.

Na primer:

pustiti objProperties = Objekt.keys(to)

Dostop do te matrike vam bo omogočil definiranje iteracijskega obnašanja predmeta.

Nato morate slediti ponovitvam predmeta. To lahko dosežete z uporabo spremenljivk števca.

Na primer:

pustiti propertyIndex = 0;
pustiti childIndex = 0;

Prvo spremenljivko števca boste uporabili za sledenje lastnostim objekta, drugo pa za sledenje podrejenim elementom lastnosti.

Nato boste morali implementirati in vrniti Naslednji metoda.

takole:

vrnitev {
Naslednji() {
// Naslednji bloki kode gredo sem ...
}
}

Znotraj Naslednji boste morali obravnavati robni primer, ki se pojavi, ko je bil celoten objekt ponovljen. Če želite obravnavati robni primer, morate vrniti predmet z vrednost nastavljena nedoločeno in Končano nastavljena prav.

Če tega primera ne obravnavamo, bo poskus iteracije po objektu povzročil neskončno zanko.

Spodaj je opisano, kako ravnati z robnim ohišjem:

če (propertyIndex > objProperties.dolžina- 1) {
vrnitev {
vrednost: nedoločeno,
Končano: prav,
};
}

Nato boste morali dostopati do lastnosti predmeta in njegovih podrejenih elementov z uporabo števčnih spremenljivk, ki ste jih prej deklarirali.

takole:

// Dostop do nadrejenih in podrejenih lastnosti
konst lastnosti = to[objProperties[propertyIndex]];

konst lastnost = lastnosti[childIndex];

Nato morate implementirati nekaj logike za povečevanje spremenljivk števca. Logika bi morala ponastaviti childIndex ko v matriki lastnosti ni več elementov in se premakne na naslednjo lastnost v objektu. Poleg tega bi se moral povečati childIndex, če so v matriki trenutne lastnosti še vedno elementi.

Na primer:

// Logika povečevanja indeksa
if (childIndex >= properties.length - 1) {
// če v podrejeni matriki ni več elementov
// ponastavitiotrokkazalo
childIndex = 0;

// Premakni se na naslednjo lastnost
propertyIndex++;
} drugače {
// Premakni se na naslednji element v podrejeni matriki
childIndex++
}

Na koncu vrnite predmet z Končano lastnost nastavljena na lažno in vrednost lastnost, nastavljena na trenutni podrejeni element v ponovitvi.

Na primer:

vrnitev {
Končano: lažno,
vrednost: lastnina,
};

Vaš dokončan Simbol.iterator funkcija mora biti podobna spodnjemu bloku kode:

iterObject[Simbol.iterator] = funkcijo () {
konst objProperties = Objekt.keys(to);
pustiti propertyIndex = 0;
pustiti childIndex = 0;

vrnitev {
Naslednji: () => {
//Ravnanje z robnim primerom
če (propertyIndex > objProperties.dolžina- 1) {
vrnitev {
vrednost: nedoločeno,
Končano: prav,
};
}

// Dostop do nadrejenih in podrejenih lastnosti
konst lastnosti = to[objProperties[propertyIndex]];

konst lastnost = lastnosti[childIndex];

// Logika povečevanja indeksa
if (childIndex >= properties.length - 1) {
// če v podrejeni matriki ni več elementov
// ponastavitiotrokkazalo
childIndex = 0;

// Premakni se na naslednjo lastnost
propertyIndex++;
} drugače {
// Premakni se na naslednji element v podrejeni matriki
childIndex++
}

vrnitev {
Končano: lažno,
vrednost: lastnina,
};
},
};
};

Tek a za...od zanka na iterObject po tej implementaciji ne bo povzročil napake, saj implementira a Simbol.iterator metoda.

Ročna implementacija iteratorjev, kot smo storili zgoraj, ni priporočljiva, ker je zelo nagnjena k napakam, logiko pa je težko upravljati.

Generatorji JavaScript

Generator JavaScript je funkcija, katere izvajanje lahko kadar koli začasno ustavite in nadaljujete. To vedenje omogoča ustvarjanje zaporedja vrednosti skozi čas.

Funkcija generatorja, ki je funkcija, ki vrne Generator, nudi alternativo ustvarjanju iteratorjev.

Generatorsko funkcijo lahko ustvarite na enak način, kot bi ustvarili deklaracijo funkcije v JavaScriptu. Edina razlika je, da morate dodati zvezdico (*) na funkcijsko ključno besedo.

Na primer:

funkcijo* primer () {
vrnitev"generator"
}

Ko pokličete običajno funkcijo v JavaScriptu, ta vrne vrednost, ki jo določa njen vrnitev ključno besedo oz nedoločeno drugače. Toda funkcija generatorja ne vrne nobene vrednosti takoj. Vrne objekt Generator, ki ga lahko dodelite spremenljivki.

Za dostop do trenutne vrednosti iteratorja pokličite Naslednji metodo na objektu Generator.

Na primer:

konst gen = primer();

console.log (gen.next()); // { vrednost: 'Generator', Končano: prav }

V zgornjem primeru je vrednost premoženje je prišlo od a vrnitev ključno besedo, ki dejansko prekine generator. To vedenje je na splošno nezaželeno pri funkcijah generatorja, saj se od običajnih funkcij razlikujejo po zmožnosti zaustavitve in ponovnega zagona izvajanja.

Ključna beseda donos

The donos ključna beseda ponuja način za ponavljanje vrednosti v generatorjih tako, da prekine izvajanje generatorske funkcije in vrne vrednost, ki ji sledi.

Na primer:

funkcijo* primer() {
donos"Model S"
donos"Model X"
donos"Cyber ​​Truck"

vrnitev"Tesla"
}

konst gen = primer();

console.log (gen.next()); // { vrednost: 'Model S', Končano: lažno }

V zgornjem primeru, ko je Naslednji metoda se kliče na primer generator, se bo zaustavil vsakič, ko naleti na donos ključna beseda. The Končano Lastnost bo nastavljena tudi na lažno dokler ne naleti na a vrnitev ključna beseda.

Klicanje Naslednji metodo večkrat na primer generator za prikaz tega, boste imeli kot rezultat naslednje.

console.log (gen.next()); // { vrednost: 'Model X', Končano: lažno }
console.log (gen.next()); // { vrednost: "Cyber ​​Truck", Končano: lažno }
console.log (gen.next()); // { vrednost: 'Tesla', Končano: prav }

konzola.log (gen.next()); // { vrednost: undefined, done: true }

Objekt Generator lahko tudi ponovite z uporabo za...od zanka.

Na primer:

za (konst iterator od gen) {
konzola.log (iterator);
}

/*
Model S
Model X
Cyber ​​Truck
*/

Uporaba iteratorjev in generatorjev

Čeprav se iteratorji in generatorji morda zdijo abstraktni koncepti, to niso. Lahko so v pomoč pri delu z neskončnimi podatkovnimi tokovi in ​​zbirkami podatkov. Uporabite jih lahko tudi za ustvarjanje edinstvenih identifikatorjev. Knjižnice za upravljanje stanja, kot je MobX-State-Tree (MST), jih prav tako uporabljajo pod pokrovom.