JQuery Kochbuch (German Edition)
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 }
----
Eine Warnung vor for...in-Schleifen
Verwenden Sie niemals eine
for...in
-Schleife,um über ein jQuery-Objekt oder ein beliebiges Array zu iterieren. Besitzt das Array eigene Eigenschaften oder Methoden, dann werden diese zusammen mit den numerischen Array-Elementen durchiteriert. So enumeriert der folgende Code nur ein einzelnes DOM-Element – den Dokumenten-Body (mit
i = 0
):
$('body').each( function( i ) { console.log( i ); });
Dieser Code sieht vielleicht so aus, als ob er das gleiche machen würde, aber er enumeriert neben dem Element
[0]
alle jQuery-Methoden wie
show
und
css
:
for( var i in $('body') ) console.log( i ); // SCHLECHT
Nutzen Sie stattdessen eine der oben aufgeführten Array-Schleifen.
Selbst die »sichere« Anwendung einer
for...in
-Schleife, um über ein Objekt zu iterieren, kann zu Problemen führen, wenn Code auf Ihrer Seite
Object.prototype
verändert hat, um alle Objekte mit zusätzlichen Methoden oder Eigenschaften zu versehen. Die Schleife enumeriert diese Methoden oder Eigenschaften zusammen mit den eigentlich gewünschten.
Es wird dringend davon abgeraten,
Object.prototype
zu erweitern, da dadurch sehr viel Code beschädigt werden kann. Tatsächlich funktioniert sogar jQuery (zumindest bis Version 1.3.2) nicht mehr wie üblich, weil
each()
damit auch die zusätzlichen Methoden oder Eigenschaften enumeriert. Wenn Ihr Code in solch einer Umgebung arbeiten muss, müssen Sie in all Ihren Schleifen zusätzliche Vorsichtsmaßnahmen treffen, wie zum Beispiel mit der Methode
hasOwnProperty()
. Leider machen diese zusätzlichen Tests den Code langsamer. Sie müssen sich also zwischen Geschwindigkeit und Robustheit entscheiden.
----
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.
Name Lookups verringern
Problem
Ihr Code hat eine innere Schleife, ganz tief verschachtelt in anderen Funktionen, die hunderte oder tausende Male ausgeführt wird. Die innere Schleife ruft diverse globale Funktionen auf und referenziert ein paar Variablen, die in den äußeren Funktionen oder global definiert wurden.
Jede dieser Referenzen löst aufgrund der verschachtelten Funktionen diverse Name Lookups aus. Damit wird Ihr Code langsamer, aber Profiler zeigen nicht, wo das Problem liegt, und aus dem Code wird auch nicht offensichtlich, dass es ein Problem gibt!
Lösung
Prüfen Sie für jeden Namen in Ihrer innersten Schleife, wie viele Name Lookups erforderlich sind. Verringern Sie die Anzahl an Name Lookups, indem Sie Objektreferenzen lokal puffern oder weniger verschachtelte Funktionen nutzen.
Diskussion
Closures sind eine wunderbare Sache. Mit ihnen ist es problemlos möglich, Statusinformationen einzufangen und sie asynchronen Funktionen – wie Eventhandlern oder Timer Callbacks – mitzugeben. Hätte JavaScript keine Closures, müsste jeder asynchrone Callback einen Weg finden, den Status weiterzugeben. Stattdessen können Sie einfach eine eingebettete Funktion nutzen.
Die dynamische Natur von JavaScript ist ebenso
Weitere Kostenlose Bücher