Andmekogude itereerimine traditsiooniliste silmuste abil võib kiiresti muutuda tülikaks ja aeglaseks, eriti kui tegemist on suurte andmemahtudega.
JavaScripti generaatorid ja iteraatorid pakuvad lahendust suurte andmekogude tõhusaks itereerimiseks. Nende abil saate juhtida iteratsioonivoogu, anda väärtusi ükshaaval ning peatada ja jätkata iteratsiooniprotsessi.
Siin käsitlete JavaScripti iteraatori põhitõdesid ja sisemisi omadusi ning seda, kuidas saate iteraatorit käsitsi ja generaatori abil genereerida.
JavaScripti iteraatorid
Iteraator on JavaScripti objekt, mis rakendab iteraatori protokolli. Need objektid teevad seda, võttes a järgmiseks meetod. See meetod tagastab objekti, mis rakendab Iteraatori tulemus liides.
The Iteraatori tulemus liides sisaldab kahte omadust: tehtud ja väärtus. The tehtud omadus on tõeväärtus, mis tagastab vale kui iteraator suudab toota oma jadas järgmise väärtuse või tõsi kui iteraator on oma jada lõpetanud.
The väärtus atribuut on JavaScripti väärtus, mille iteraator selle järjestuse ajal tagastab. Kui iteraator lõpetab oma jada (millal tehtudtõsi), see vara tagastab määratlemata.
Nagu nimigi viitab, võimaldavad iteraatorid teil "itereerida" JavaScripti objekte, nagu massiivid või kaardid. Selline käitumine on võimalik itereeritava protokolli tõttu.
JavaScriptis on itereeritav protokoll standardne viis objektide määratlemiseks, mida saate itereerida, näiteks jaoks... kohta silmus.
Näiteks:
konst puuviljad = ["banaan", "Mango", "Õun", "Viinamarjad"];
jaoks (konst iteraator kohta puuviljad) {
konsool.log (iteraator);
}
/*
Banaan
Mango
Apple
Viinamarjad
*/
See näide kordab üle puuviljad massiivi kasutades a jaoks... kohta silmus. Igas iteratsioonis logib see konsooli praeguse väärtuse. See on võimalik, kuna massiivid on itereeritavad.
Mõned JavaScripti tüübid, näiteks massiivid, stringid, Komplektid ja kaardid, on sisseehitatud itereeritavad, kuna need (või mõni nende prototüübiahelas olev objekt) rakendavad @@iteraator meetod.
Muud tüübid, näiteks objektid, ei ole vaikimisi itereeritavad.
Näiteks:
konst iterObject = {
autod: ["Tesla", "BMW", "Toyota"],
loomad: ["Kass", "koer", "Hamster"],
toit: ["Burgerid", "Pitsa", "Pasta"],
};jaoks (konst iteraator kohta iterObject) {
konsool.log (iteraator);
}
// TypeError: iterObject ei ole itereeritav
See näide näitab, mis juhtub, kui proovite itereerida objekti, mis ei ole itereeritav.
Objekti itereeritavaks muutmine
Objekti itereeritavaks muutmiseks peate rakendama a Sümbol.iteraator meetod objektil. Itereeritavaks muutumiseks peab see meetod tagastama objekti, mis rakendab Iteraatori tulemus liides.
The Sümbol.iteraator sümbol täidab sama eesmärki kui @@iteraator ja seda saab kasutada „spetsifikatsioonis” vaheldumisi, kuid mitte koodis as @@iteraator ei ole kehtiv JavaScripti süntaks.
Allolevad koodiplokid pakuvad näidet selle kohta, kuidas muuta objekt itereeritavaks, kasutades iterObject.
Esiteks lisage Sümbol.iteraator meetod selleks iterObject kasutades funktsioon deklaratsiooni.
Nagu nii:
iterObject[Sümbol.iterator] = funktsiooni () {
// Järgnevad koodiplokid lähevad siia...
}
Järgmiseks peate pääsema juurde kõikidele selle objekti võtmetele, mida soovite itereeritavaks muuta. Võtmetele pääsete juurde kasutades Objekt.võtmed meetod, mis tagastab objekti loendatavate omaduste massiivi. Massiivi tagastamiseks iterObject’s võtmed, anna edasi see märksõna argumendina Objekt.võtmed.
Näiteks:
lase objProperties = Objekt.keys(see)
Juurdepääs sellele massiivile võimaldab teil määrata objekti iteratsioonikäitumise.
Järgmisena peate jälgima objekti iteratsioone. Seda saate saavutada loendurite abil.
Näiteks:
lase propertyIndex = 0;
lase lapseindeks = 0;
Esimest loenduri muutujat kasutate objekti omaduste jälgimiseks ja teist atribuudi laste jälgimiseks.
Järgmisena peate rakendama ja tagastama järgmiseks meetod.
Nagu nii:
tagasi {
next() {
// Järgnevad koodiplokid lähevad siia...
}
}
Sees järgmiseks meetodi puhul peate käsitlema servajuhtumit, mis ilmneb siis, kui kogu objekti on itereeritud. Servajuhtumi käsitlemiseks peate tagastama objekti koos väärtus seatud määratlemata ja tehtud seatud tõsi.
Kui seda juhtumit ei käsitleta, tekib objekti üle itereerimisel lõpmatu tsükkel.
Edaspidi toimige järgmiselt.
kui (propertyIndex > objProperties.pikkus- 1) {
tagasi {
väärtus: määratlemata,
tehtud: tõsi,
};
}
Järgmiseks peate pääsema juurde objekti atribuutidele ja nende alamelementidele, kasutades varem deklareeritud loenduri muutujaid.
Nagu nii:
// Juurdepääs vanema- ja alamomadustele
konst omadused = see[objProperties[propertyIndex]];
konst omadus = omadused[lapseindeks];
Järgmiseks peate rakendama loenduri muutujate suurendamise loogikat. Loogika peaks lähtestama lapseindeks kui atribuudi massiivis pole enam elemente ja liigub objekti järgmise atribuudi juurde. Lisaks peaks see suurenema lapseindeks, kui praeguse atribuudi massiivis on veel elemente.
Näiteks:
// Indeksi suurendamise loogika
if (childIndex >= omadused.pikkus - 1) {
// kui alammassiivis pole enam elemente
// lähtestadalapsindeks
lapseindeks = 0;
// Liigu järgmisele atribuudile
propertyIndex++;
} muidu {
// Liikumine alammassiivi järgmise elemendi juurde
lapseindeks++
}
Lõpuks tagastage objekt koos tehtud vara määratud vale ja väärtus atribuut seatakse iteratsiooni praegusele alamelemendile.
Näiteks:
tagasi {
tehtud: vale,
väärtus: vara,
};
Teie lõpetatud Sümbol.iteraator funktsioon peaks olema sarnane alloleva koodiplokiga:
iterObject[Sümbol.iterator] = funktsiooni () {
konst objProperties = Objekt.keys(see);
lase propertyIndex = 0;
lase lapseindeks = 0;tagasi {
järgmine: () => {
//Käsitlemine serva juhtumiga
kui (propertyIndex > objProperties.pikkus- 1) {
tagasi {
väärtus: määratlemata,
tehtud: tõsi,
};
}// Juurdepääs vanema- ja alamomadustele
konst omadused = see[objProperties[propertyIndex]];
konst omadus = omadused[lapseindeks];// Indeksi suurendamise loogika
if (childIndex >= omadused.pikkus - 1) {
// kui alammassiivis pole enam elemente
// lähtestadalapsindeks
lapseindeks = 0;
// Liigu järgmisele atribuudile
propertyIndex++;
} muidu {
// Liikumine alammassiivi järgmise elemendi juurde
lapseindeks++
}
tagasi {
tehtud: vale,
väärtus: vara,
};
},
};
};
Jooksmine a jaoks... kohta silmus sisse iterObject pärast seda teostust ei tekita tõrge, kuna see rakendab a Sümbol.iteraator meetod.
Iteraatorite käsitsi juurutamine, nagu me eespool tegime, ei ole soovitatav, kuna see on väga veatundlik ja loogikat võib olla raske hallata.
JavaScripti generaatorid
JavaScripti generaator on funktsioon, mille täitmise saate igal hetkel peatada ja jätkata. Selline käitumine võimaldab tal aja jooksul luua väärtuste jada.
Generaatori funktsioon, mis tagastab generaatori, pakub alternatiivi iteraatorite loomisele.
Saate luua generaatorifunktsiooni samamoodi nagu JavaScriptis funktsiooni deklaratsiooni. Ainus erinevus on see, et peate lisama tärni (*) funktsiooni märksõna juurde.
Näiteks:
funktsiooni* näiteks () {
tagasi"Generaator"
}
Kui kutsute JavaScriptis tavalist funktsiooni, tagastab see selle määratud väärtuse tagasi märksõna või määratlemata muidu. Kuid generaatorifunktsioon ei tagasta kohe väärtust. See tagastab generaatori objekti, mille saate muutujale määrata.
Iteraatori praeguse väärtuse juurde pääsemiseks helistage järgmiseks meetodit generaatori objektil.
Näiteks:
konst gen = näide();
console.log (gen.next()); // { väärtus: "Generaator", tehtud: tõsi }
Ülaltoodud näites on väärtus vara pärines a tagasi märksõna, peatades tõhusalt generaatori. Selline käitumine on generaatorifunktsioonide puhul üldiselt ebasoovitav, kuna tavafunktsioonidest eristab neid võime täitmist peatada ja taaskäivitada.
Saagise märksõna
The saagikus Märksõna annab võimaluse generaatorites väärtuste kordamiseks, peatades generaatorifunktsiooni täitmise ja tagastades sellele järgneva väärtuse.
Näiteks:
funktsiooni* näiteks() {
saagikus"Mudel S"
saagikus"Mudel X"
saagikus"Küberveok"tagasi"Tesla"
}konst gen = näide();
console.log (gen.next()); // { väärtus: "Model S", tehtud: vale }
Ülaltoodud näites, kui järgmiseks meetodit kutsutakse näiteks generaator, peatub see iga kord, kui ta kohtab saagikus märksõna. The tehtud vara määratakse ka vale kuni see kohtab a tagasi märksõna.
Helistades järgmiseks meetodil mitu korda näiteks generaator, et seda demonstreerida, on teie väljundiks järgmine.
console.log (gen.next()); // { väärtus: "Model X", tehtud: vale }
console.log (gen.next()); // { väärtus: "Küberveok", tehtud: vale }
console.log (gen.next()); // { väärtus: "Tesla", tehtud: tõsi }
konsool.log (gen.next()); // { väärtus: määramata, tehtud: tõene }
Samuti saate itereerida üle generaatori objekti, kasutades jaoks... kohta silmus.
Näiteks:
jaoks (konst iteraator kohta gen) {
konsool.log (iteraator);
}
/*
Mudel S
Mudel X
Küberveoauto
*/
Iteraatorite ja generaatorite kasutamine
Kuigi iteraatorid ja generaatorid võivad tunduda abstraktsete mõistetena, ei ole nad seda nii. Need võivad olla abiks lõpmatute andmevoogude ja andmekogudega töötamisel. Saate neid kasutada ka kordumatute identifikaatorite loomiseks. Olekuhalduse raamatukogud, nagu MobX-State-Tree (MST), kasutavad neid ka kapoti all.