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 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. 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. 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. 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. 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: 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. 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: 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); Ö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. 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 . Létezik egy tömb, var mas = csak pozitív számokat tartalmazó tömböt kell használni a filter módszerrel. 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.
Használati példa: 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: Var a = ["a", "b", "c"]; var index; for (index = 0; index< a.length; ++index) {
console.log(a);
}
Var a = ["a", "b", "c"]; var index, len; for (index = 0, len = a.length; index< len; ++index) {
console.log(a);
}
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); ) 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);
}
}
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;
}
For (kulcs be a) ( if (arrayHasOwnIndex(a, kulcs)) ( console.log(a); ) ) For (kulcs in a) ( if (a.hasOwnProperty(key) && String(parseInt(kulcs, 10)) === kulcs) ( console.log(a; ) ) 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. Példa a következő használatára:... Varval; var a = ["a", "b", "c"]; for (a érték) ( console.log(val); ) Var a = ["a", "b", "c"]; var it = a.entries(); var bejegyzés; while (!(bejegyzés = it.next()).kész) ( console.log(entry.value); ) 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)); // (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)); Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0); Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0); 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: 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: 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. 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. 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. 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. 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): Ú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) => "
2014 Régen Gondolkozz logikusan. Ezt nézd For(változó index = 0 , hossz = tömb.hossz ; index< length ; index++) {
//do stuff
}
Most pedig mondd el, miért lenne gyorsabb, mint: Változó hossza = array.length; while(--length) ( //vagy hossz-- //do stuff ) 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: Á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: 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 -Minden módszerhez
szűrési módszer
térkép módszer
Módszerek mindegyik/egyes
redukál/reduceRight
ö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
Eredmények
Feladatok
Szerezz egy új tömböt
Szűrje le a tömböt
Ellenőrizze a tömböt
I. Iteráció valós tömbök felett
Jelenleg háromféleképpen lehet ismételni egy valódi tömb elemeit:
Emellett hamarosan, az új ECMAScript 6 (ES 6) szabvány megjelenésével további két módszer várható: 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.
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.2. A hurokhoz
Jó öreg a szabályokhoz:
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. :
Elméletileg ennek a kódnak kicsit gyorsabban kell futnia, mint az előzőnek.
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.
Ebben a példában a ciklus minden iterációja során két ellenőrzést hajtanak végre:
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.
Ezután a példa hurok törzse jelentősen csökken:
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ő: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.
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:
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.
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:
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 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:
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ó:
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:
Frissítés: Ahogy a megjegyzésekben megjegyeztükaz egyes
szűrő
mindegyik/néhány
térkép
redukál/reduceRight
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; ) )