Schleifen programmieren
Problem
Sie rufen $.each(array,fn)
oder $(selector).each(fn)
auf, um in Ihrem Code über
tausende von Elementen zu iterieren, und vermuten, dass all diese
Funktionsaufrufe das Laden Ihrer Seite verlängern:
$.each( array, function() {
// tue etwas mit this
});
oder
$('.lotsOfElements').each( function() { // tue etwas mit this oder $(this) });
Lösung
Verwenden Sie eine for
-Schleife anstelle von .each()
. Um über ein Array zu iterieren, gibt
es kaum eine schnellere Möglichkeit:
for( var item, i = −1; item = array[++i] ) {
// tue etwas mit item
}
Aber sie hat einen Nachteil: diese Schleife
funktioniert nur, wenn Ihr Array keine »leeren« Elemente enthält,
also Elemente, deren Wert undefined
,
null
, false
, 0
oder
""
ist. Selbst mit dieser
Einschränkung ist diese Schleife jedoch in vielen häufig
auftretenden Situationen nützlich, zum Beispiel beim Iterieren über
ein jQuery-Objekt. Stellen Sie nur sicher, dass Sie das Objekt in
einer Variablen puffern:
var $items = $('.lotsOfElements');
for( var item, i = −1; item = $item[++i] ) {
// tue etwas mit item (ein DOM-Knoten)
}
Häufig liegen auch JSON-Daten vor, die ein Array mit Objekten enthalten – wie bei unserem Beispiel aus Tabellen schneller laden:
{ "names": [ { // ... "zip": "48786" }, // für 1000 Namen wiederholt ] }
Wenn Sie wissen, dass keines dieser Objekte,
die das Array names
aufbauen, jemals
null sein wird, können Sie die schnelle Schleife nutzen.
Ein allgemeinerer Ansatz, der mit jedem Array funktioniert, ist die klassische Schleife, aud die Sie immer wieder stoßen werden:
for( var i = 0; i < array.length; i++ ) {
var item = array[i];
// tue etwas mit item
}
Doch diese Schleife lässt sich trotzdem auf unterschiedliche Weisen verbessern:
- Puffern der Arraylänge
- Verwenden von
++i
, was in manchen Browsern schneller ist alsi++
- Kombinieren des Tests mit der Erhöhung der Schleifenvariablen zur Vermeidung eines Name Lookups
Das Ergebnis ist:
for( var i = −1, n = array.length; ++i < n; ) {
var item = array[i];
// tue etwas mit item
}
Note
Wäre es vielleicht sogar noch schneller, eine
while
-Schleife oder eine do...while
-Schleife zu nutzen? Wahrscheinlich
nicht. Sie könnten die eben angeführte Schleife auch wie folgt
schreiben:
var i = −1, n = array.length;
while( ++i < n ) {
var item = array[i];
// tue etwas mit item
}
oder
var i = 0, n = array.length;
if( i < n ) do {
var item = array[i];
// tue etwas mit item
}
while( ++i < n );
Aber keine davon ist schneller als die besser
lesbare for
-Schleife.
Um über ein Objekt (kein Array) zu iterieren,
können Sie eine for..in
-Schleife
verwenden:
for( var key in object ) {
var item = object[key];
// tue etwas mit item
}
Diskussion
$(selector).each(fn)
ist der übliche Weg, ein
jQuery-Objekt zu erzeugen und darüber zu iterieren, aber es ist
nicht der einzige. Das jQuery-Objekt ist ein »Array-ähnliches«
Objekt mit einer .length
-Eigenschaft
und [0]
, [1]
, ...
,
[length-1]
. Daher können Sie beliebige
Schleifen nutzen, die Sie auch bei anderen Arrays verwenden. Und da
das jQuery-Objekt niemals »leere« Elemente enthält, können Sie die
am Anfang dieser Lösung präsentierte, schnellste for
-Schleife verwenden.
Wenn Sie die Funktion time()
aus Was ist an $(this) falsch? oder einen anderen
Profiler nutzen, um die Performance von Schleifen zu messen,
sollten Sie auf jeden Fall den »echten« Code testen, keine
vereinfachte Testversion, die nur die Schleife ohne den
Schleifenrumpf testet. Diese vereinfachten Tests würden einen
potenziellen Vorteil der for
-Schleife
übersehen: Weniger Name Lookups aufgrund einer reduzierten
Funktionsverschachtelung. In Name Lookups verringern finden Sie mehr Details
dazu.