Melyik kódot használjátok?
Melyik megközelítést használjátok a kettő közül, és miért?
1.)2.)(A forEach-et most felejtsük el egy pillanatra.)
■ 1.)
var a = [0,1,2];
for (var i=0, l=a.length; i<l; ++i) {
var v = a[i];
//...
}
var a = [0,1,2];
for (var i=0, l=a.length; i!=l; ++i) {
var v = a[i];
//...
}
Lehetőség szerint az
Itt ugyan nincs jelentősége, de jobb megszokni, hogy ilyen esetben ne egyenlőségre vizsgálj, mert vannak helyzetek, amikor az ==, ===, != végtelen ciklusba viszik a programot.
Ilyesmire gondoltál?
Persze, de kíváncsi vagyok a
De ugye majd elmondod, hogy
A végtelen ciklushoz való
Nekem ha nem kacsacsőrt teszek, akkor az a 15 éves beidegződés fut át az agyamon, hogyha valamiért átugorja a length értéket az index - mondjuk a kozmikus sugárzás miatt - akkor végtelen ciklusba kerül a program. Sok éve js-ben ilyenkor lefagyott a böngésző, és elég kényelmetlen volt újraindítgatni és debuggolni, hogy vajon hol van a végtelen ciklus.
Manapság már nincs ilyen probléma több ok miatt sem:
- Végtelen ciklusnál megkérdi a böngésző, hogy leállítsa e a programot.
- TDD-vel fejlesztve pontosan lehet tudni, hogy hol a hiba a kódban.
- Általában az ember nem törődik előre az optimalizálással, és forEach-et használ.
Ha integereket vizsgálsz,
Okés, kösz az infot.
Első
kisebb
A másik gyorsabb lenne amúgy? Vagy miért jó? Ha ez szól mellette én akkor sem használnám ezt a micro optimalizációt.
Mindazonáltal egy
echo $x.'bigyo'.$y;
vs.
echo $x,'bigyo',$y;
optimalizálást simán meglépek, mert nem ront az olvashatóságon.
Assembly/gépi szinten
Amikor utoljára assembly-ben programoztam, akkor egy xor művelet, utána meg ha jól emlékszem, egy jz/jnz utasítás, ami összeségében két órajel ciklust igényelt, míg a hasonlítás hármat vagy többet.
Ciklusokra meg volt olyan, hogy decrement (lehetőleg regisztert) és utána a jz/jnz (ugrás ha nulla/nem nulla az eredmény)
Nem egészen
Egyenlőségvizsgálat
Amit ebből haza lehet vinni, hogy nincs számottevő különbség. Ez pont az a zóna, ahol a döntés hatása elvész a JIT fordító optimizálása okozta zajban.
Nem mostani processzorokról
(ezeknek már nem ismerem az assembly-jét/gépikódját - amit emlegettem... azon még tudtam, hogy mi, hány órajelciklust igényel :) )
Egyébként is ciklusszervezésről volt szó, ami korábban úgy nézett ki assemly szinten, hogy (többnyire) regiszterbe töltve a lefutások darabszáma, azt egy decrement utasítással csökkentem és a decrement mögé csak egy olyan jump kellett, ami a decrement által beállított flag függvényében ugrott, ha az eredmény nulla lett.
Ennek a helyére betenni egy hasonlító műveletet, rengeteget tudott lassítani a kódon.
Ezek 8086-os utasítások, én
Igen, a klasszikus ciklusvezérlés asm-ben az, amikor a cx regiszer tartalmazza a futások számát, ezt a cikus végén egyel csökkentjük, majd ha ez eredmény nem nulla ugrunk a cikus elejére (dec cx, jnz cikus) - ezt a kettőt egyszerre elköveti a loop utasítás.
Erre csak akkor fordítható le biztonsággal egy JS ciklus, ha a cikusváltozóra nem hivatkozunk a ciklusmagban (vagyis nincs elvárás a programozó részéről az i által felvett értékekről).
Néhányan írnak pl ilyen (lefelé számláló) cikust az optimalzálás jegyében, ezt el tudom képzelni, hogy ez valódi natív asm loppá fordul:
Én viszont elakadtam valahol
Azóta nem foglalkoztam assembly-vel :(
Én mindig az elsőt használom,
Egyiket sem
var
kulcsszó a cikluson belül félrevezető lehet.Ha nem számít a sorrend, akkor a következőt szoktam használni:
+1
harmadikat (negyediket)
folytonos?
false
,null
,undefined
,NaN
,""
,0
feltételezem,
Melyik a kakukktojás? :D elem
utolsó
||
:)A középső :-) Ha nem teszed
ez igaz :)
Igen, ha array[i] = 0, akkor
array[i] = 0
, akkor azelem
Igaz. Aki másnak vermet ás...
jah
Szerintem ha nem tartalmaz
Szerk.: eh, ez nyilván hülyeség, a második olyan végtelen ciklust okoz, hogy öröm nézni, mivel az elem előző értéke nem lesz undefined, amikor pont kilépnénk a tömbből. Az állításom úgy helyes, ha nem ciklusban vizsgáljuk a dolgot, hanem
array[i] = 1
, ez esetben mindhárom sor 1-et ad vissza, és a || utáni rész nem értékelődik ki :).Egyik sem okoz végtelen
A második pedig azt okoz.
1. Az
elem = array[i] || elem !== undefined
esetén a vizsgálat időpontjában az elem mindig még az előző értéket tartja.2. Az elem értéke az értékadás után vagy array[i] lesz (ha az array[i] truthy) vagy true (ha array[i] undefined) vagy false (ha array[i] falsy de nem undefined).
Tehát nem csak egy plusz kört fog menni, mivel az elem soha nem lesz === undefined. A ciklus csak akkor nem lesz végtelen, ha a tömb üres vagy az első értéke falsy, ez esetben még az első kör előtt leáll.
Jó volt a felvetésed, mert még másnapra is alig sikerült teljesen kibogoznunk :).
elem = array[i] || elem !==
- truthy, ha array[i] truthy vagy az előző elem nem undefined volt.
- false, ha array[i] falsy és az előző elem undefined volt.
Na most az előző elem csak az elején lehet undefined. Utána mindenképp truthy lesz a végtelenségig. Nem egyszerű végiggondolni :D
Ja pedig ránézésre egy holt egyszerű kód... :-)
Nem, igazad van, tényleg csak
Az első falsy érték esetében true-t ad az érték helyett, mert
array[i] || array[i] !== undefined
ezt állítja be értéknek azarray[i]
helyett.A másodikkal ennél egy fokkal érdekesebb. Az elem az
array[i] || elem !== undefined
értéket kapja, így haarray[0]
alatt falsy értékkel találkozik, akkor el sem indul a ciklus, mivel az elem értéke a kiindulási állapotban undefined. A végén még valószínűleg hozzácsap plusz egy kört, mivel azelem !== undefined
mindig az előző értéket nézi.A harmadik
(elem = array[i]) || elem !== undefined
a zárójel miatt gyakorlatilag megegyezik azzal, hogyelem = array[i], elem || elem !== undefined
, szóval az helyes.Na látom mindenkit sikerült összezavarni a végére, még magamat is... :D
:-)
Jó látni, hogy mennyi
Még ezen is lehet szépíteni azért:
Kövezzetek meg
Kiegészítés
+1
És - szerintem - sokkal olvashatóbb is, és ha már forráskódról beszélünk, legyen is olvasható.
Első, kizárólag :)