Kapcsolatok

Tulajdonságok iterálása objektumokban. JQuery - Tömbön, objektumon és elemeken keresztül történő hurokolás kifejezetten iterátor használatával

Ez így működik:

// ECMASCRIPT 2015+ SZÜKSÉGES var s, myStringArray = ["Hello", "World"]; for (s of myStringArray) ( // ... csináljon valamit az s-vel ... )

Vagy ami még jobb, mivel az ECMAScript 2015 blokk-hatókörű változókat is biztosít let és const paraméterekkel:

// ECMASCRIPT 2015+ SZÜKSÉGES const myStringArray = ["Hello", "World"]; for (const s of myStringArray) ( // ... csináljon valamit az s-vel ... ) // s itt már nincs definiálva

Megjegyzés a ritka tömbökről: előfordulhat, hogy a JavaScript tömbje valójában nem tárol annyi elemet, amennyit a hosszában megadott; ez a jelentett szám egyszerűen eggyel nagyobb, mint a legmagasabb index, amelyen az értéket tárolják. Ha egy tömb kevesebb elemet tartalmaz, mint amennyit a hossza jelzi, akkor ritkanak mondjuk. Például teljesen legális, ha egy tömb csak a 3-as, 12-es és 247-es indexnél tartalmaz elemeket; Egy ilyen tömb hossza 248, bár valójában csak 3 értéket tárol. Ha más indexen próbálja elérni az elemet, akkor a tömbnek definiálatlan értéke lesz. Tehát amikor egy tömböt szeretne "iterálni", meg kell válaszolnia a kérdést: szeretné-e az iterációt a hossza által meghatározott teljes tartományon keresztül, és a hiányzó elemeket undefined feldolgozni, vagy csak a elemek valóban jelen vannak? Mindkét megközelítésre számos alkalmazás létezik; ez csak attól függ, hogy mire használod a tömböt.

Ha egy tömbön keresztül iterál a for .. of értékkel, akkor a ciklus törzse a hossz alapján kerül végrehajtásra, és a ciklusvezérlő változó nem definiált minden olyan elemnél, amely valójában nem szerepel a tömbben. A „csináljon valamit” kódjának részleteitől függően ez a viselkedés lehet az, amit szeretne, de ha nem az, amit szeretne, akkor más megközelítést kell alkalmaznia.

Természetesen néhány fejlesztőnek nincs más választása, mint más megközelítést alkalmazni, mert valamilyen oknál fogva olyan JavaScript-verziót céloznak meg, amely még nem támogatott ... / .

Mindaddig, amíg a JavaScript megvalósítása kompatibilis az ECMAScript specifikáció egy korábbi verziójával (amely például kizárja az Internet Explorer 9 előtti verzióit), ciklus helyett használhatja az Array#forEach iterator metódust. Ebben az esetben átad egy függvényt, amely a tömb minden eleméhez meghívódik:

Var myStringArray = [ "Hello", "World" ]; myStringArray.forEach(function(s) ( // ... csinálj valamit az s-sel ... ));

A ... of függvénytől eltérően a .forEach csak a ténylegesen értékeket tartalmazó elemeken hívja meg a függvényt. Ha átadjuk a hipotetikus tömbünket három elemmel és 248 hosszúsággal, akkor csak háromszor hívja meg a függvényt, nem 248-szor. Különbséget tesz a hiányzó és a ténylegesen undefined értékre beállított elemek között is; az utóbbi esetében továbbra is meghívja a függvényt, és egy definiálatlan értéket ad át argumentumként. Ha így szeretné kezelni a ritka tömböket, akkor a .forEach lehet a megfelelő út, még akkor is, ha a fordítója támogatja a ... of .

Az utolsó lehetőség, amely a JavaScript minden verziójában működik, egy explicit számlálóhurok. Egyszerűen 0-tól eggyel kevesebbet számol a hossznál, és a számlálót használja indexként. A fő hurok így néz ki:

Ennek a megközelítésnek az egyik előnye, hogy kiválaszthatja, hogyan kezelje a ritka tömböket; A fenti kód a ciklus törzsét a teljes hosszon futtatja úgy, hogy az s értéke undefined legyen a hiányzó elemekhez, például a .. / . Ha ehelyett csak egy ritka tömb ténylegesen meglévő elemeit szeretné feldolgozni, például .forEach , akkor egy egyszerű ellenőrzést adhat az indexhez:

Var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length; for (i=0; i

A hossz érték hozzárendelése egy helyi változóhoz (szemben azzal, hogy a teljes myStringArray.length kifejezést belefoglalja a hurokfeltételbe) jelentős hatást gyakorolhat a teljesítményre, mivel minden alkalommal kihagyja a tulajdonságkeresést egészen a végéig; Ha a Rhino-t használom a gépemen, a sebesség 43%.

Láthatja, hogy a hossza gyorsítótárazás a hurok inicializálási záradékában történik, így:

Var i, len, myStringArray = [ "Hello", "World" ]; for (len = myStringArray.length, i=0; i

A mások által említett szintaxisban szereplő for ... egy objektum tulajdonságainak ciklusára szolgál; mivel a JavaScript tömbje csak egy objektum numerikus tulajdonságnevekkel (és egy automatikusan frissülő hossz tulajdonsággal), elméletileg hurkolhatja vele a tömböt. De a probléma az, hogy nem korlátozódik a numerikus tulajdonságértékekre (ne feledje, hogy a metódusok is valójában csak tulajdonságok, amelyek értéke egy lezárás), és nem garantált, hogy numerikus sorrendben megismétlődik. Ezért a szintaxisban szereplő for ... nem használható a tömbök közötti ciklusra.

Helló! Folytatjuk a tömbmódszerek tanulmányozását, és ebben a leckében a tömbön keresztüli iteráció módszereit vizsgáljuk meg. Ezek a módszerek lehetővé teszik egy tömb bejárását és bizonyos műveletek végrehajtását az elemein. Igen, elfelejtettem mondani, hogy ezeket a módszereket az IE 8 nem támogatja. Bár most olyan fontos, hogy ez a böngésző nem támogatja őket, de mégis, ha IE8 támogatást szeretnél, akkor az ES5-shim segít. És folytatjuk

Minden módszerhez

Ezzel a módszerrel egy tömb hurokban való bejárására szolgál, de átadhatunk neki egy függvényt, amelyben bizonyos műveleteket hajthatunk végre a tömb elemein. Nézzünk egy példát.

Var mas = ["Banán", "Avokádó", "Sárgarépa"]; mas.forEach(function(item, i, mas) ( alert(i + ": " + item + " (tömb: " + mas + ")"); ));

Itt a példában egy függvényt adunk át a forEach metódusnak, amely 3 paramétert ad meg:

tétel- tömb elem

én— tömbelem száma

mas— a feldolgozás alatt álló tömb.

Ez a módszer használható a for ciklus helyett a tömbön keresztüli iterációhoz.

szűrési módszer

Ez a metódus a forEach metódushoz hasonlóan egy tömbön való iterációra szolgál, és argumentumként ad át egy függvényt, de lehetővé teszi a tömb szűrését, és egy új tömböt ad vissza, amely csak azokat az elemeket tartalmazza, amelyekhez az általunk átadott függvény ehhez a módszerhez igazat ad vissza.

Kicsit zavaros, ezért nézzük meg egy példával.

Var mas = ; var pozitívNum = mas.filter(függvény(szám) ( visszatérési szám > 0; )); document.write(pozitívSzám); 1,4,3

A példában van egy számokat tartalmazó tömb, és egy másik tömböt kell kapnunk, amely csak pozitív számokat tartalmazna az eredeti tömbből. Ehhez alkalmazzuk a tömbre a filter metódust, és meghívunk egy függvényt, ami minden elemet ellenőriz, azaz minden pozitív számot visszaad, és az eredményt egy másik tömbben tároljuk, a példában ez pozitívNum.

térkép módszer

A map metódus egy másik tömböt hoz létre, amely az eredeti tömb függvényének meghívásának eredményeiből fog állni, de ebben a függvényben bizonyos műveletek az eredeti tömb elemein történnek, és az eredmény úgy jelenik meg az új tömbben, ahogy van. Nézzünk egy példát, egyébként szerintem teljesen homályos.

Var mas = ; var newMas = mas.map(function(item) ( return item*item; )); // kapott egy tömböt négyzetekkel alert(newMas); 1,4,9

A példában van egy kezdeti tömb számokkal, erre van alkalmazva a map metódus, amelyben a tömb minden elemét megszorozzuk önmagával és az eredményt egy másik tömbbe írjuk. Ennek eredményeként egy tömböt kapunk az eredeti tömbben lévő számok négyzeteivel.

Módszerek mindegyik/egyes

Ezek a módszerek ellenőrzik, hogy van-e elem a tömbben. Ezt egy olyan függvényen keresztül teszik meg, amelyet paraméterként adnak át nekik, vagyis ha ez a függvény igazat ad vissza, akkor maga a metódus is igazat ad vissza. Ezen túlmenően minden metódus megköveteli, hogy minden elem megfeleljen a függvény feltételének, néhány módszer pedig legalább egy egyezést. És mint mindig, itt is van egy példa az Ön számára.

Var mas = ; function isPositiv(num) ( visszatérési szám > 0; ) if(mas.every(isPositiv)) ( document.write("A tömb csak pozitív számokat tartalmaz"); ) else( document.write("A tömb legalább egyet tartalmaz negatív szám "); ) if(mas.some(isPositiv)) ( document.write("A tömb legalább egy pozitív számot tartalmaz"); ) else ( document.write("Nincsenek pozitív számok a tömbben") ;)

Vegyünk egy példát: van egy tömbünk pozitív és negatív számokkal, és ellenőriznünk kell, hogy van-e benne legalább egy negatív szám. Ehhez minden és néhány módszert alkalmazunk. Létrehozunk egy függvényt, amely pozitív számokat ad vissza, majd minden metódusnak átadja, mivel ez a metódus logikai eredményt ad vissza, ezért feltételes utasításokban használatos. Példánkban minden metódus hamis értéket ad vissza, mert negatív számok vannak a tömbben, de néhány metódus igazat ad vissza, mert legalább egy pozitív szám van a tömbben.

redukál/reduceRight

Ha egy tömbön keresztül kell iterálni, használhatja a forEach, for or for..of parancsot.

Ha egy tömbön keresztül kell iterálnia, és minden elemhez adatokat kell visszaadnia, használja a térképet.

Mód arr.csökkenteniÉs arr.reduceRight Hasonlóak a fenti módszerekhez, de kissé bonyolultabbak. Egyetlen érték kiszámítására szolgálnak a teljes tömb alapján.

Szintaxis:

Legyen érték = arr.reduce(function(previousÉrték, elem, index, tömb) ( // ... ), );

A függvény a tömb minden elemére felváltva kerül alkalmazásra, és az eredményét „átviszi” a következő hívásba.

Érvek:

  • previousValue – ennek a függvénynek az előző hívásának eredménye, amely megegyezik az első hívás kezdeti értékével (ha a kezdetet átadtuk),
  • item – a tömb következő eleme,
  • index – indexe,
  • array – maga a tömb.

Amikor egy függvényt meghívunk, a tömb előző elemére vonatkozó hívás eredménye első argumentumként kerül átadásra.

Ez bonyolultnak hangzik, de egyszerűbbé válik, ha úgy gondolja, hogy az első argumentum az előző függvényhívások eredményének „felhalmozása”. Ha kész, a redukció eredménye lesz.

Ez a módszer a legkönnyebben megérthető, mint mindig, egy példával.

Itt megkapjuk a tömb összes elemének összegét egyetlen sorban:

Legyen arr = ; legyen eredmény = arr.reduce((összeg, áram) => összeg + áram, 0); riasztás(eredmény); 15

Itt a leggyakoribb redukciós opciót használtuk, amely csak 2 argumentumot használ.

Nézzük meg közelebbről, hogyan működik.

  1. Az első futtatáskor az összeg kezdeti (a redukció utolsó argumentuma), ami 0, az áram pedig a tömb első eleme, ami 1. Így a függvény eredménye 1.
  2. Amikor másodszor futtatjuk az összeg = 1-et, hozzáadjuk a tömb második elemét (2).
  3. A harmadik futásnál összeg = 3, amihez hozzáadjuk a következő elemet, és így tovább...

A számítási folyamat így néz ki:

Táblázat formájában, ahol minden sor egy függvényhívás a tömb következő elemén:

összeg jelenlegi eredmény
első hívás 1 1
második hívás 1 2 3
harmadik kihívás 3 3 6
negyedik kihívás 6 4 10
ötödik kihívás 10 5 15

Itt jól látható, hogy az előző hívás eredménye hogyan kerül át a következő hívás első argumentumába.

A kezdeti értéket is elhagyhatjuk:

Legyen arr = ; // a kezdeti érték eltávolításra kerül (nincs 0 a végén) legyen result = arr.reduce((sum, current) => sum + current); riasztás(eredmény); 15

Az eredmény pontosan ugyanaz! Ennek az az oka, hogy inicializálás hiányában a tömb első eleme lesz az 1. érték, és a keresés a másodiktól kezdődik.

A számítási táblázat ugyanaz lesz, mínusz az első sor.

De az ilyen használat rendkívüli óvatosságot igényel. Ha a tömb üres, a redukció kezdeti érték nélküli hívása hibát okoz.

Íme egy példa:

Legyen arr = ; // Hiba: Kezdőérték nélküli üres tömb redukálása // ha lenne kezdőérték, a redukció visszaadná egy üres tömbnél. arr.reduce((összeg, áram) => összeg + áram);

Eredmények

Összefoglalva tehát megvizsgáltuk a tömbök ciklusban történő munkavégzésének különféle módszereit, amelyek mindegyikében közös, hogy mindegyiknek át kell adnia egy függvényt argumentumként.

  • forEach – egy tömbön való hurkoláshoz.
  • filter – a tömb szűrése. Új szűrt tömböt ad vissza
  • every/some – az egyes elemek meglétének ellenőrzése a tömbben.
  • map - tömb tömbbé alakítása. Az eredeti konvertált tömböt adja vissza.
  • Reduction/reduceRight – Kiszámít egy értéket a teljes tömbből, minden elemen függvényt hív, és a köztes eredményt átadja a hívások között. Használható a tömbelemek összegének kiszámítására.

Feladatok

Szerezz egy új tömböt

Legyen adott a var mas = ["HTML", "CSS", "JavaScript", "Pascal"] tömb, a map metódussal kell egy új tömböt kapni, amely tartalmazza az eredeti tömb egyes elemeinek hosszát .

Szűrje le a tömböt

Létezik egy tömb, var mas = csak pozitív számokat tartalmazó tömböt kell használni a filter módszerrel.

Ellenőrizze a tömböt

Van egy tömb var mas = ellenőrizni kell, hogy vannak-e negatív számok a tömbben, és az eredményt megjeleníteni a képernyőn.

Nos, végezetül egy rövid videó a tömbön való hurkoláshoz.

  • Fordítás
  • I. Iteráció valós tömbök felett
    1. Minden módszerhez és a kapcsolódó módszerekhez
    2. hurokhoz
    3. A for...in loop megfelelő használata
    4. for... of loop (az iterátor implicit használata)
    5. Az iterátor kifejezett használata
    1. Metódusok használata valós tömbökön való iterációhoz
    2. Konvertálja valódi tömbbé
    3. Megjegyzés a futásidejű objektumokról

I. Iteráció valós tömbök felett

Jelenleg háromféleképpen lehet ismételni egy valódi tömb elemeit:
  1. metódus Array.prototype.forEach ;
  2. klasszikus for loop
  3. egy „helyesen” megkonstruált...in hurok.
Emellett hamarosan, az új ECMAScript 6 (ES 6) szabvány megjelenésével további két módszer várható:
  1. for... of loop (az iterátor implicit használata);
  2. az iterátor explicit használata.

1. A forEach módszer és a kapcsolódó módszerek

Ha projektjét úgy tervezték, hogy támogassa az ECMAScript 5 (ES5) szabvány funkcióit, használhatja annak egyik újítását - a forEach módszert.

Használati példa:
var a = ["a", "b", "c"]; a.forEach(function(entry) ( console.log(entry); ));
Általában a forEach használatához csatlakozni kell az es5-shim emulációs könyvtárhoz azoknál a böngészőknél, amelyek natívan nem támogatják ezt a módszert. Ezek közé tartozik az IE 8 és korábbi verziók, amelyek néhol még mindig használatban vannak.

A forEach előnye, hogy nincs szükség helyi változók deklarálására az aktuális tömbelem indexének és értékének tárolásához, mivel ezek automatikusan átadódnak a visszahívási függvénynek argumentumként.

Ha aggódik az egyes elemek visszahívásának lehetséges költségei miatt, ne aggódjon, és olvassa el ezt.

A ForEach-et úgy tervezték, hogy egy tömb összes elemén át iteráljon, de ezen kívül az ES5 számos további hasznos módszert kínál az összes vagy néhány elem iterálásához, valamint bizonyos műveletek végrehajtásához:

  • Az every - igazat ad vissza , ha a tömb minden elemére a visszahívás egy igazra konvertálható értéket ad vissza .
  • some - igazat ad vissza, ha a tömb legalább egy elemére a visszahívás igazra konvertálható értéket ad vissza.
  • szűrő - létrehoz egy új tömböt, amely tartalmazza az eredeti tömb azon elemeit, amelyekre a visszahívás igazat ad vissza.
  • térkép - létrehoz egy új tömböt, amely a visszahívás által visszaadott értékekből áll.
  • redukció – egyetlen értékre csökkenti a tömböt, minden egyes tömbelemre felváltva visszahívást alkalmaz, az elsőtől kezdve (hasznos lehet a tömbelemek és egyéb összegző függvények összegének kiszámításához).
  • ReductionRight – a redukcióhoz hasonlóan működik, de fordított sorrendben iterálja az elemeket.

2. A hurokhoz

Jó öreg a szabályokhoz:

Var a = ["a", "b", "c"]; var index; for (index = 0; index< a.length; ++index) { console.log(a); }
Ha a tömb hossza állandó a ciklusban, és maga a ciklus a kód teljesítménykritikus szakaszához tartozik (ami nem valószínű), akkor használhatja a "optimálisabb" verziót, amely tárolja a tömb hosszát. :

Var a = ["a", "b", "c"]; var index, len; for (index = 0, len = a.length; index< len; ++index) { console.log(a); }
Elméletileg ennek a kódnak kicsit gyorsabban kell futnia, mint az előzőnek.

Ha az elemek sorrendje nem fontos, akkor még tovább lehet lépni az optimalizálás terén, és megszabadulni a tömb hosszának tárolására szolgáló változótól, megváltoztatva a keresés sorrendjét fordítottra:

Var a = ["a", "b", "c"]; var index; for (index = a.length - 1; index >= 0; --index) ( console.log(a); )
A modern JavaScript-motorokban azonban az ilyen optimalizáló játékok általában semmit sem jelentenek.

3. A for...in ciklus helyes használata

Ha a for...in ciklus használata javasolt, ne feledje, hogy a tömbökön keresztüli iteráció nem az, amire való. Az elterjedt tévhittel ellentétben a for...in ciklus nem tömbindexeken keresztül iterál, hanem egy objektum számtalan tulajdonságain keresztül.

Bizonyos esetekben azonban, például a ritka tömbökön történő iteráció, a for...in hasznos lehet, ha megteszi az alábbi példában látható óvintézkedéseket:

// a - ritka tömb var a = ; a = "a"; a = "b"; a = "c"; for (var key in a) ( if (a.hasOwnProperty(key) && /^0$|^\d*$/.test(key) && kulcs<= 4294967294) { console.log(a); } }
Ebben a példában a ciklus minden iterációja során két ellenőrzést hajtanak végre:

  1. hogy a tömbnek van saját kulcs nevű tulajdonsága (nem a prototípusától örökölt).
  2. ez a kulcs egy olyan karakterlánc, amely egy 4294967294-nél kisebb egész szám decimális reprezentációját tartalmazza. Honnan származik az utolsó szám? Az ES5 tömbindexének definíciójából, amely azt mutatja, hogy egy tömb elemének legmagasabb indexe lehet: (2^32 - 2) = 4294967294 .
Természetesen az ilyen ellenőrzések felesleges időt vesznek igénybe a ciklus végrehajtásakor. De ritka tömb esetén ez a módszer hatékonyabb, mint a for ciklus, mivel ebben az esetben csak azokat az elemeket iteráljuk, amelyek a tömbben kifejezetten definiáltak. Tehát a fenti példában csak 3 iteráció kerül végrehajtásra (a 0, 10 és 10000 indexeknél) a for ciklus 10001-gyel szemben.

Annak érdekében, hogy ne írjon ilyen nehézkes ellenőrző kódot minden alkalommal, amikor egy tömbön keresztül kell iterálnia, megírhatja külön függvényként:

Függvény arrayHasOwnIndex(tömb, kulcs) ( return array.hasOwnProperty(kulcs) && /^0$|^\d*$/.test(kulcs) && kulcs<= 4294967294; }
Ezután a példa hurok törzse jelentősen csökken:

For (kulcs be a) ( if (arrayHasOwnIndex(a, kulcs)) ( console.log(a); ) )
A fent tárgyalt ellenőrző kód univerzális, minden esetre alkalmas. De ehelyett használhat egy rövidebb verziót is, bár formailag nem teljesen helyes, de a legtöbb esetben megfelelő:

For (kulcs in a) ( if (a.hasOwnProperty(key) && String(parseInt(kulcs, 10)) === kulcs) ( console.log(a; ) )

4. For...of ciklus (az iterátor implicit használata)

A még tervezet állapotú ES6-nak be kell vezetnie az iterátorokat a JavaScriptbe.

Iterátor egy objektum által megvalósított protokoll, amely szabványos módot határoz meg egy értéksorozat (véges vagy végtelen) megszerzésére.
Az iterátor egy next() metódust definiáló objektum – egy argumentum nélküli függvény, amely két tulajdonságú objektumot ad vissza:

  1. kész (boolean) – igaz, ha az iterátor elérte az iterálható sorozat végét. Ellenkező esetben az érték hamis.
  2. érték – az iterátor által visszaadott értéket határozza meg. Lehet undefined (hiányzó), ha a done tulajdonság igaz .
Számos beépített objektum, pl. A valódi tömbök alapértelmezés szerint iterátorokkal rendelkeznek. Az iterátor valódi tömbökön való használatának legegyszerűbb módja az új for...of konstrukció használata.

Példa a következő használatára:...

Varval; var a = ["a", "b", "c"]; for (a érték) ( console.log(val); )
A fenti példában a for...of ciklus implicit módon meghívja az Array objektum iterátorát, hogy megkapja a tömb minden értékét.

5. Az iterátor kifejezett használata

Az iterátorok explicit módon is használhatók, azonban ebben az esetben a kód sokkal bonyolultabb lesz a for...of ciklushoz képest. Valahogy így néz ki:

Var a = ["a", "b", "c"]; var it = a.entries(); var bejegyzés; while (!(bejegyzés = it.next()).kész) ( console.log(entry.value); )
Ebben a példában az Array.prototype.entries metódus egy iterátort ad vissza, amely a tömb értékeinek megjelenítésére szolgál. Minden iterációnál az enter.value egy [kulcs, érték] alakú tömböt tartalmaz.

II. Iteráció tömbszerű objektumok felett

A valódi tömbök mellett a JavaScriptben is vannak tömbszerű objektumok . Közös bennük a valós tömbök, hogy rendelkeznek egy hossz tulajdonsággal és a tömb elemeinek megfelelő számokkal elnevezett tulajdonságokkal. A példák közé tartozik a NodeList gyűjtemény DOM-ja és a pszeudotömb argumentumok, amelyek bármely függvényen/metóduson belül elérhetők.

1. Metódusok használata valós tömbök feletti iterációhoz

Legalább a legtöbb, ha nem az összes valós tömbön keresztüli iterációs módszer használható tömbszerű objektumok iterációjára.

A for és for...in konstrukciók pontosan ugyanúgy alkalmazhatók tömbszerű objektumokra, mint a valódi tömbökre.

A ForEach és más Array.prototype metódusok tömbszerű objektumokra is vonatkoznak. Ehhez a Function.call vagy a Function.apply parancsot kell használni.

Például, ha a forEach-t alkalmazni szeretné egy csomópont objektum childNodes tulajdonságára, akkor ezt a következőképpen tegye:

Array.prototype.forEach.call(node.childNodes, function(child) ( // csinálj valamit a gyermekobjektummal));
A trükk újrafelhasználásának megkönnyítése érdekében deklarálhat egy hivatkozást az Array.prototype.forEach metódusra egy külön változóban, és használhatja azt parancsikonként:

// (Feltéve, hogy az összes alábbi kód ugyanabban a hatókörben van) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // csinálj valamit a gyermekobjektummal));
Ha egy tömbszerű objektumnak van iterátora, akkor ez ugyanúgy használható explicit vagy implicit módon az objektum feletti iterációra, mint a valódi tömbök esetében.

2. Konvertálás valódi tömbbé

Van egy másik, nagyon egyszerű módja is egy tömbszerű objektum feletti iterációnak: konvertálja azt valódi tömbbé, és használja a fent tárgyalt módszerek bármelyikét a valós tömbök feletti iterációhoz. Az átalakításhoz használhatja az általános Array.prototype.slice metódust, amely bármilyen tömbszerű objektumra alkalmazható. Ez nagyon egyszerűen megtehető, amint az az alábbi példában látható:

Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);
Például, ha egy NodeList gyűjteményt tényleges tömbbé szeretne konvertálni, valami ehhez hasonló kódra lesz szüksége:

Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);
Frissítés: Ahogy a megjegyzésekben megjegyeztük

2016. március 12

A modern JavaScriptben vannak úgynevezett „iterációs módszerek”, amelyeket a tömbökön keresztüli iterációra használnak. Ebben az oktatóanyagban a következő módszereket ismertetjük:

az egyes

A .forEach() metódus használatos keresés sor. Meghívja az ún. callback függvényt, melynek segítségével három paraméter item, i, arr kerül átadásra, ahol:

  • item — tömbelem;
  • i a tömb sorozatszáma;
  • Az arr maga a tömb, amelyet ismételni kell.

A módszer használatának könnyebb megértése érdekében nézzünk meg egy példát:

Var user=["admin","pass",31]; user.forEach(function(elem,i,user)( alert("A cikkszám értéke " + i + " : " + elem); ));

Ez a módszer használható a szokásos for ciklus helyett.

szűrő

A .filter() metódus a szűrésre szolgál, ez is használja a visszahívási függvényt, de új tömböt hoz létre, ha a tömb elemei megegyeznek a true értékkel:

Var arr=; var newArr=arr.filter(function(number)( visszatérési szám< 0; }); alert(newArr); // выведет -34,-4

Ebben a példában a rendszer ellenőrzi a számok negatív értékeit, és a kimenet egy új tömb ezekkel az értékekkel. Megállapíthatja a saját feltételeit, ezeknek nem kell feltétlenül számoknak lenniük.

mindegyik/néhány

Ez a két módszer hasonló egymáshoz, és mindkettőt egy tömb ellenőrzésére használják, csak a metódust .minden() igaz értéket ad vissza, ha a tömb összes értéke megegyezik a megadott feltétellel és a metódussal .néhány() igazat ad vissza, ha legalább egy érték megfelel a feltételnek:

Var arr=; alert(arr.every(function(number)( visszatérési szám< 0; })); // выведет false

Remélem egyértelmű, hogy ha a fenti példában használtuk valamilyen módszert akkor hamis helyett igaz értéket jelenítettünk volna meg.

térkép

A .map() metódus átalakítja a tömböt, és újat kap belőle. Minden a visszahívási függvény meghívásával történik:

Var arr=; var newArr=arr.map(függvény(szám)( visszatérési szám*2; )); alert(newArr);

Ebben a példában egy új tömböt kaptunk az elemek kétszeres értékével.

redukál/reduceRight

Az utolsó módszerek, amelyeket megvizsgálunk, a redukció és a redukció. A tömb egyes elemeinek feldolgozására szolgálnak, miközben elmentik a köztes eredményt. A módszer balról jobbra iterál minden elemet, a reductionRight pedig az ellenkezőjét teszi. Más módszerekkel ellentétben a visszahívási függvényen kívül itt a kezdeti érték argumentum is megadásra kerül - „kezdeti érték”. Ráadásul a visszahívási funkció megadja a „köztes eredményt” - előzőÉrtékÉs aktuális elem— a tömb aktuális eleme.

Nézzünk egy példát:

Függvény getSums(arr) ( var result = ; if (!arr.length) return result; var totalSum = arr.reduceRight(function(sum, item) ( result.push(sum); return sum + item; )); eredmény .push(totalSum); eredményt ad vissza; ) alert(getSums()); 1,3,6,10,15

Mi történt ebben a példában? Létrehoztunk egy függvényt, amivel új tömböt kaphatunk az előzőek összegéből létrehozott elemekkel. Sőt, az elemek jelentése a végéről származik. És itt van egy egyszerűbb példa, amelyben létrehoztam egy függvényt, amely kiszámítja egy tömb elemeinek összegét:

Függvény getSum(arr) ( var result = arr.reduce(function(sum, current) ( return sum + current )); return result; ); alert(getSum()); Címkék: 

22 válasz

A teszt futtatása után a legtöbb modern böngészővel...

Jelenleg a ciklus leggyorsabb formája (és véleményem szerint szintaktikailag a legkézenfekvőbb).

szabvány hosszúságú gyorsítótárazott hurokhoz

For (var i = 0, len = myArray.length; i< len; i++) { }

Azt mondanám, hogy ez egy olyan eset, amikor üdvözlöm a JavaScript motor fejlesztőit. A végrehajtási időt optimalizálni kell világosság, nem a kényelem kedvéért.

2016 júniusától, számos teszt a legújabb Chrome-ban (2016 májusában a böngészőpiac 71%-a, és növekszik):

  • A leggyorsabb ciklus a ciklus ciklusa, gyorsítótár hosszával és anélkül is, nagyon hasonló teljesítményt biztosítva. (A gyorsítótárazott hosszúságú for ciklus néha jobb eredményeket produkál, mint a nem gyorsítótárazott, de a különbség szinte elhanyagolható, ami azt jelenti, hogy a motor optimalizálható a szabványos és talán a legegyszerűbb gyorsítótár nélküli ciklus javára).
  • A csökkentésekkel rendelkező while ciklus körülbelül 1,5-szer lassabb volt, mint a for ciklus.
  • A visszahívási funkciót használó hurok (pl. standard forEach) körülbelül 10-szer lassabb volt, mint a for hurok.

Úgy gondolom, hogy ez a szál túl régi, és a programozók úgy érzik, hogy gyorsítótárba kell helyezniük a hosszt, vagy visszacsökkentő metszéspontokat kell használniuk a jobb teljesítmény elérése érdekében, olyan kódot írva, amely kevésbé válogatós és hibásabb, mint egy egyszerű for-loop. Ezért javaslom:

    Ha az alkalmazás sok elemen keresztül iterál, vagy a cikluskód egy gyakran használt függvényen belül van, egy egyenes ciklus a válasz:

    For (i változó = 0; i< arr.length; i++) { // Do stuff with arr[i] or i }

    Ha az alkalmazás nem igazán iterál sok elemet, vagy csak kis iterációkat kell végrehajtania itt-ott, a szabványos forEach visszahívás vagy bármely hasonló funkció használata a választott JS-könyvtárból tisztább és kevésbé hibás, mivel az index A változó hatóköre privát, és Ön Nincs szükség zárójelek használatára, amelyek közvetlenül hozzáférnek a tömb értékéhez:

    Arr.forEach(függvény(érték, index) ( // Dolgozzon értékkel vagy indexszel ));

    Ha valóban szüksége van néhány ezredmásodpercre, miközben sorok milliárdjain át iterál, és a tömb hossza nem változik a folyamat során, fontolja meg a hossz gyorsítótárba helyezését egy for ciklusban. Bár szerintem erre manapság már tényleg nincs szükség:

    For (var i = 0, len = arr.length; i< len; i++) { // Do stuff with arr[i] }

Még csak 2018 van, szóval jó lehet egy frissítés...

És tényleg kellene nem ért egyet az elfogadott válasszal. Különböző böngészőktől függ. van, amelyik a forEach-et gyorsabban, mások a for-loop-ot, míg mások az összes módszert tesztelik http://jsben.ch/mW36e

Arr.forEach(a => ( // ... )

és mivel sok for(a = 0;...) ciklust láthat, például for(a = 0;...), érdemes megemlíteni, hogy változók nélkül a "var" globálisan lesz definiálva, és ennek jelentős hatása lehet sebesség, tehát lassú lesz.

var arr = arr = new Tömb(11111111).fill(255); var benches = [ [ "üres", () =>< l; a++); }] , ["for-loop", () =>( for(var a = 0, l = arr.length; a< l; ++a) var b = arr[a] + 1; }] , ["for-loop++", () =>( for(var a = 0, l = arr.length; a< l; a++) var b = arr[a] + 1; }] , ["for-loop - arr.length", () =>( for(var a = 0; a< arr.length; ++a) var b = arr[a] + 1; }] , ["reverse for-loop", () =>( for(var a = arr.length - 1; a >= 0; --a) var b = arr[a] + 1; )] ,["while-loop", () => ( var a = 0 , l = arr.length; while(a< l) { var b = arr[a] + 1; ++a; } }] , ["reverse-do-while-loop", () =>( var a = arr.length - 1; // FIGYELEM do ( var b = arr[a] + 1; ) while(a--); )] , ["forEach", () => ( arr.forEach( a => ( var b = a + 1; )); )], ["for..in (csak 3,3%)", () => ( var ar = arr.slice(0,arr.length/33) ; for(const a in ar) ( var b = a + 1; ) )] , ["Duff eszköz", () => ( var i = 0; var r = arr.length % 8; var n = (arr .length - r) / 8; if (r > 0) do ( var b = arr + 1; ) while (--r); if (n > 0) do ( var b = arr[i] + 1; var c = arr + 1; var d = arr + 1; var e = arr + 1; var f = arr + 1; var g = arr + 1; var h = arr + 1; var k = arr + 1; i = --n >>> 3; ) while (n); )] , ["Duff eszköz negatív", () => ( var r = arr.length % 8; var n = (arr.length-r) / 8 ; ///Math.floor(arr.length / 8); var i = arr.length ; // -1; while(r)( var b = arr[--i] + 1; --r; ) while (n)( var b = arr[i] + 1; var c = arr + 1; var d = arr + 1; var e = arr + 1; var f = arr + 1; var g = arr + 1; var h = arr + 1, var j = arr + 1, i = --n >>> 3; ) )]]; function bench(title, f) ( var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log("$(title) $(t1-t0) ) msec"); ) var globalVarTime = bench("for-loop "var" nélkül", () => ( // Ha elfelejtette beírni a "var" szót, akkor a változók globálisak lesznek for(a = 0, l =arr.length;a< l; ++a) var b = arr[a] + 1; }); var times = benches.map(function(a) { arr = new Array(11111111).fill(255); return }).sort((a,b) =>a-b); var max = idők; times = times.map(a => (a = (a/max)*100; return a; )); var template = (cím, idő, n) => "

" + "$(cím) " + " $(Szám(idő.Fixed(3)))msec" + "
"; var strRes = times.map(t => template(...t)).join("\n") + "

for-loop "var" nélkül $(globalVarTime) msec."; var $container = document.getElementById("container"); $container.innerHTML = strRes; body ( color:#fff; háttér:#333; font-family :helvetica; ) body > div > div ( clear:ther ) body > div > div > span ( float:left; szélesség:43%; margó:3px 0; text-align:right; ) body > div > div > span :nth-child(2) ( text-align:left; background: darkkorange; animation:showup .37s .111s; -webkit-animation:showup .37s .111s; ) @keyframes showup ( from ( szélesség:0; ) ) @-webkit-keyframes megjelenítése ( from ( szélesség:0; ) )

2014 Régen

Gondolkozz logikusan.

Ezt nézd

For(változó index = 0 , hossz = tömb.hossz ; index< length ; index++) { //do stuff }

  • Legalább 2 változót kell létrehoznia (index, hossz)
  • Ellenőrizze, hogy a hosszjelző kisebb-e, mint
  • Az indexet növelni kell
  • a for ciklusnak 3 paramétere van

Most pedig mondd el, miért lenne gyorsabb, mint:

Változó hossza = array.length; while(--length) ( //vagy hossz-- //do stuff )

  • Egy változó
  • Nincs csekk
  • csökken az index (a gépek ezt preferálják)
  • Míg csak egy paramétere van

Teljesen összezavarodtam, amikor a Chrome 28 megmutatta, hogy a for ciklus gyorsabb, mint az idő. Valami ilyesminek kellene lennie

"Nos, mindenki for ciklust használ, a krómnál koncentráljunk erre."

De most 2014-ben a while ciklus visszatér a krómhoz. 2x gyorsabb, más/régi böngészőkben mindig gyorsabb volt.

Mostanában csináltam néhány új tesztet. A valós envoirement világban ezek a rövid kódok értéktelenek, és a jsperf valójában nem tudja megfelelően végrehajtani a while ciklust, mert újra kell létrehoznia az array.length fájlt, ami szintén időbe telik.

NEM LEHET lekérni a while ciklus tényleges sebességét a jsperf-en.

létre kell hoznia saját függvényét, és ellenőriznie kell, hogy a window.performance.now()

És igen... egy darabig nincs mód arra, hogy gyorsabb legyen.

Az igazi probléma a tényleges manipuláció/lejátszási idő/rajzolási idő, vagy aminek nevezzük.

Például van egy vászonjelenetem, ahol koordinátákat és ütközéseket kell számolnom... ez 10-200 MicroSeconds (nem ezredmásodperc) között történik. valójában minden ezredmásodpercbe telik. Ugyanaz, mint a DOM-ban.

Van egy másik szuper hatékony módja a ciklus használatának bizonyos esetekben... például egy tömb másolására/klónozására

For(var i = array.length; i > 0; arrayCopy[ --i ] = array[ i ] // dolgok elvégzése);

Kérjük, vegye figyelembe a paraméter beállításokat:

  • Ugyanaz, mint a while ciklusban. Csak egy változót használok
  • Ellenőriznie kell, hogy az index nagyobb-e 0-nál;
  • Mint látható, ez a megközelítés eltér a mindenki által használt szokásos ciklustól, mivel én a 3. paraméteren belül csinálok dolgokat, és közvetlenül a tömbön belül is csökkentem.

Állítólag ez megerősíti, hogy az olyan gépek, mint pl

azt írta, hogy gondoltam lerövidítem egy kicsit és eltávolítok néhány haszontalan dolgot, és ezt írtam ugyanabban a stílusban:

For(var i = array.length ; i-- ; arrayCopy[ i ] = array[ i ] // dolgok elvégzése);

Még ha rövidebb is, úgy tűnik, hogy az i ismételt használata mindent lelassít. Ez 1/5-tel lassabb, mint az előző for és while ciklus.

Jegyzet:; nagyon fontos for looo nélkül ()

Még akkor is, ha az imént mondtam, hogy a jsperf nem a legjobb módja a szkriptek tesztelésének. 2 hurkot adtam ide.

És itt van egy másik válasz a javascript teljesítményéről

Ennek a válasznak meg kell mutatnia a javascript írásának hatékony módjait. Tehát ha ezt nem tudja elolvasni, kérdezzen és kap választ, vagy olvasson el egy könyvet a javascriptről http://www.ecma-international.org/ecma-262/5.1/

Az általam készített teszt legújabb verziója (egy régebbi teszt újrafelhasználásával) egy dolgot mutat.

A gyorsítótár hossza nem olyan fontos, de nem árt.

A fent hivatkozott teszt minden első futtatása (az újonnan megnyílt lapon) a legjobb eredményt adja az utolsó 4 töredékre (3., 5., 7. és 10. a diagramokon) Chrome-ban, Opera-ban és Firefoxban a 64 bites Debian Squeeze-emen ( az asztali hardverem). A későbbi futtatások egészen más eredményt adnak.

A teljesítményre vonatkozó következtetések egyszerűek:

  • Lépjen egy for ciklusba (előre), és ellenőrizze helyette a !==-t< .
  • Ha nem kell később újra felhasználni a tömböt, akkor a csökkentett hosszúságú ciklus és a destruktív array shift() -ing is hatásos.

Jelenleg (2011.10) az alábbi sablon tűnik a leggyorsabbnak.

For (var i = 0, len = arr.length; i !== len; i++) ( ... )

Ne feledje, hogy az arr.length gyorsítótárazás itt nem kritikus, ezért csak tesztelheti az i !== arr.length értéket, és nem lesz teljesítményhiány, de rövidebb kódot kap.

PS: Tudom, hogy a shift()-es töredékben az eredménye használható a 0. elem elérése helyett, de valahogy figyelmen kívül hagytam, hogy az előző revízió újrafelhasználása után (amelynek a ciklusok során rossz volt az értéke), és később nem akartam elveszíteni a már elért eredményeket.

„Legjobb”, mint a tiszta teljesítményben? vagy teljesítmény ÉS?

A tiszta "legjobb" teljesítmény az, amely a gyorsítótárat és a ++ előtag operátort használja (adataim: http://jsperf.com/caching-array-length/189)

For (var i = 0, len = myArray.length; i< len; ++i) { // blah blah }

Azt mondanám, hogy a gyorsítótár nélküli ciklus a legjobb egyensúly a végrehajtási idő és a programozói olvasási idő között. Minden C/C++/Java-val kezdődő programozó nem költ ms-t ennek elolvasására

For(var i=0; i< arr.length; i++){ // blah blah }

** gyorsítótárazza a tömb hosszát a cikluson belül, néhány másodpercnyi idő elcsúszik. A tömb elemeitől függ, ha több elem van a tömbben, akkor nagy különbség van az Ms idő tekintetében*

SArr; //Sor; for(var i = 0 ; i

SArr; //Sor; for(var i = 0,len = sArr.length ; i< len ; i++) { callArray(sArr[i]); //function call } ***end: 1.354ms***

Ez az év 2017 .

Csináltam néhány tesztet.

Úgy tűnik, hogy a while módszer a leggyorsabb a Chrome-ban.

Úgy tűnik, a bal oldali csökkentés (--i) sokkal gyorsabb, mint a többi (++i , i-- , i++) Firefoxban.

Ez a megközelítés átlagosan böjt. De fordított sorrendben iterálja a tömböt.

Legyen i = array.length; while (--i >= 0) ( doSomething(tömb[i]); )

Ha fontos a prioritási sorrend, használja ezt a megközelítést.

Legyen ii = array.length; legyen i = 0; miközben én< ii) { doSomething(array[i]); ++i; }

Mindig az első stílusban írok.

Még akkor is, ha a fordító elég okos ahhoz, hogy tömbökre optimalizálja, de akkor is okos, ha itt a DOMNodeList-et használjuk, vagy valami összetett objektumot kiszámított hosszúsággal?

Tudom, hogy a kérdés a tömbökre vonatkozik, de szerintem jó gyakorlat, ha minden ciklusodat ugyanabban a stílusban írod.

Var arr = ; // A tömb var i = 0; miközben én< arr.length) { // Do something with arr[i] i++; }

Az i++ gyorsabb, mint az ++i, --i és i -



Tetszett a cikk? Oszd meg