Die Ankunft von jQuery hat den Prozess zum Schreiben von JavaScript lächerlich vereinfacht. Sie werden jedoch feststellen, dass kleine Änderungen an Ihrem Code die Lesbarkeit und / oder Leistung erheblich verbessern. Hier sind einige Tipps, wie Sie Ihren Code optimieren können.
Wir benötigen eine solide Plattform, um unsere Tests durchzuführen. Hier ist das HTML-Markup für die Testseite, auf der alle Tests ausgeführt werden:
Leistungsverbesserungen testen - Siddharth / NetTuts+ Text hier
- Oh, hallo!
Hier ist nichts Besonderes. Nur ein paar Elemente, die wir anvisieren und testen können. Wir verwenden Firebug, um die Zeiten hier zu protokollieren. Profil beginnt den Prozess und profileEnd stoppt es und notiert, wie lange die Aufgabe gedauert hat. Normalerweise verwende ich die Hauptprofilmethode von Firebug, aber für unsere falschen Zwecke ist dies ausreichend.
Wie in vielen Fällen liefern Sie eine einzige Skriptdatei, die Ihren Code für alle Seiten Ihrer Site enthält. Hierbei handelt es sich normalerweise um Code, der häufig Aktionen für nicht vorhandene Elemente auf der aktuellen Seite ausführt. Obwohl jQuery Probleme wie diese recht ordentlich behandelt, heißt das nicht, dass Sie Probleme einfach ignorieren können. Wenn Sie die Methoden von jQuery für eine leere Sammlung aufrufen, werden sie nicht ausgeführt.
Als bewährte Methode sollten Sie nur Code ausführen, der auf die aktuell geladene Seite anwendbar ist, anstatt den gesamten Code in einer einzigen Dokument-Ready-Prüfung zu bündeln und an den Client zu liefern.
Schauen wir uns das erste Szenario an:
console.profile (); var ele = $ ("# somethingThatisNotHere"); ele.text ("etwas Text"). slideUp (300) .addClass ("Bearbeitung"); $ ("# mainItem"); console.profileEnd (); // Hier gibt es noch mehr fantastischen, bodenständigen Code ._.
Firebug's spuckt folgendes Ergebnis aus:
Lassen Sie uns diesmal prüfen, ob das Element, für das Sie Aktionen ausführen möchten, vorhanden ist, bevor Sie dies tun.
console.profile (); var ele = $ ("# somethingThatisNotHere"); if (ele [0]) ele.text ("Text"). slideUp (300) .addClass ("Bearbeitung"); $ ("# mainItem"); console.profileEnd (); // Hier gibt es noch mehr fantastischen, bodenständigen Code ._.
Und die Ergebnisse:
Sehen? Es ist ziemlich einfach, auf den Punkt und erledigt die Arbeit. Beachten Sie, dass Sie nicht prüfen müssen, ob für jedes einzelne Bit Ihres Codes ein Element vorhanden ist. Sie werden auf Ihrer Seite feststellen, dass bestimmte größere Teile im Allgemeinen von dieser Methode profitieren. Verwenden Sie hier Ihr Urteil.
Versuchen Sie, eine ID zu verwenden, anstatt eine Klasse zu übergeben.
Dies ist ein großes Thema, deshalb halte ich es so kurz wie möglich. Wenn Sie Selektoren übergeben, versuchen Sie zunächst, eine ID zu verwenden, anstatt eine Klasse zu übergeben. jQuery verwendet das native direkt getElementById Eine Methode, um ein Element anhand der ID zu finden, während im Fall einer Klasse ein internes Voodoo ausgeführt werden muss, um es zumindest in älteren Browsern zu erhalten.
Wir werden die verschiedenen Selektoren betrachten, die Sie als Ziel für die 2. Wahl verwenden können li Element. Wir werden jeden von ihnen testen und wie sie die Leistung verändern.
Die erste Methode, die einfachste, besteht darin, sie einfach mit der ausgewählt Klasse. Mal sehen, was Firebugs Profiler zurückgibt.
console.profile (); $ (". ausgewählt"); console.profileEnd ();
Und das Ergebnis: 0.308ms. Als Nächstes wird ein Tag-Name vorangestellt, um ihn einzugrenzen. Auf diese Weise können wir unsere Suche eingrenzen, indem wir zunächst nur die ausgewählten DOM-Elemente mit document.getElementsByTagName anvisieren.
console.profile (); $ ("li.selected"); console.profileEnd ();
Und das Ergebnis: 0.291ms. Etwa 0,02 ms wurden rasiert. Dies ist vernachlässigbar, da wir in Firefox testen. Es ist jedoch zu beachten, dass diese Leistungssteigerung in älteren Browsern wie Internet Explorer 6 deutlich höher sein wird.
Als Nächstes gehen wir von der ID des übergeordneten Elements aus.
console.profile (); $ ("# someList .selected"); console.profileEnd ();
Und das Ergebnis: 0.283ms. Versuchen wir etwas genauer zu sein. Neben der ID des Vorfahren geben wir auch den Elementtyp an.
console.profile (); $ ("# someList li.selected"); console.profileEnd ();
Und das Ergebnis: 0,275 ms. Ein weiterer kleiner Teil wurde rasiert. Schließlich lassen Sie uns es direkt mit einer ID auf zielen.
console.profile (); $ ("# mainItem"); console.profileEnd ();
Und das Ergebnis: 0,165 ms. Beeindruckend! Dies zeigt Ihnen wirklich, wie viel schneller native Methoden ausgeführt werden. Beachten Sie, dass moderne Browser zwar Vorteile wie getElementsByClassName nutzen können, ältere Browser jedoch nicht. Dies führt zu einer viel langsameren Leistung. Berücksichtigen Sie dies immer beim Codieren.
Sizzle, das von John Resig erstellte Selector-Modul von jQuery, analysiert die Selektoren von rechts nach links, wodurch einige unerwartete Parsing-Ketten entstehen.
Betrachten Sie diesen Selektor:
$ ("# someList .selected");
Wenn Sizzle auf einen solchen Selektor stößt, erstellt es zunächst die DOM-Struktur, verwendet den Selektor als Stamm, verwirft Elemente, die nicht über die erforderliche Klasse verfügen, und prüft für jedes Element mit der Klasse, ob das übergeordnete Element eine ID hat someList.
Um dies zu berücksichtigen, stellen Sie sicher, dass der ganz rechte Teil Ihrer Auswahl so genau wie möglich ist. Zum Beispiel durch Angabe ausgewählt anstatt .ausgewählt, Sie reduzieren die Anzahl der zu prüfenden Knoten. Dies ist der Grund, warum die Leistung im vorherigen Abschnitt zugenommen hat. Durch das Hinzufügen zusätzlicher Einschränkungen wird die Anzahl der zu prüfenden Knoten effektiv reduziert.
Um die Art und Weise, wie Elemente erhalten werden, besser abzustimmen, sollten Sie für jede Anforderung einen Kontext hinzufügen.
var someList = $ ('# someList') [0]; $ (". selected", someList);
Durch das Hinzufügen eines Kontexts ändert sich die Suchart des Elements vollständig. Nun das Element, das den Kontext bereitstellt - someList In unserem Fall - wird zuerst gesucht, und sobald es abgerufen wurde, werden untergeordnete Elemente, die nicht die erforderliche Klasse haben, entfernt.
Beachten Sie, dass es im Allgemeinen eine bewährte Methode ist, ein DOM-Element als Kontext Ihres jQuery-Selektors zu übergeben. Die Verwendung eines Kontexts ist am hilfreichsten, wenn er in einer Variablen gespeichert wird. Ansonsten können Sie den Prozess rationalisieren und find () verwenden - was jQuery selbst unter der Haube tut.
$ ('# someList'). find ('. selected');
Ich möchte sagen, dass die Leistungssteigerung klar definiert wird, aber ich kann nicht. Ich habe Tests mit einer Reihe von Browsern durchgeführt und davon, ob die Performance des Scope-Ansatzes die der Vanilla-Version übertrifft, hängt von einer Reihe von Faktoren ab, beispielsweise davon, ob der Browser bestimmte Methoden unterstützt.
Wenn Sie durch den Code eines anderen Benutzers navigieren, werden Sie häufig finden.
// Anderer Code $ (Element) .doSomething (); // mehr Code $ (Element) .doSomethingElse (); // Noch mehr Code $ (Element) .doMoreofSomethingElse ();
Bitte mach das nicht. Je. Der Entwickler instanziiert dieses "Element" immer wieder. Das ist verschwenderisch.
Mal sehen, wie viel Zeit ein solcher horrender Code benötigt, um zu laufen.
console.profile (); $ ("# mainItem"). hide (); $ ("# mainItem"). val ("Hello"); $ ("# mainItem"). html ("Oh, hey da!"); $ ("# mainItem"). show (); console.profileEnd ();
Wenn der Code nacheinander wie oben aufgebaut ist, können Sie die Verkettung wie folgt verwenden:
console.profile (); $ ("# mainItem"). hide (). val ("Hello"). html ("Oh, hey da!"). show (); console.profileEnd ();
Durch die Verkettung wird das ursprünglich übergebene Element erfasst, und eine Referenz wird an alle nachfolgenden Aufrufe weitergegeben, wodurch die Ausführungszeit verkürzt wird. Andernfalls wird jedes Mal ein neues jQuery-Objekt erstellt.
Wenn jedoch die Abschnitte, auf die sich das Element bezieht, nicht gleichzeitig sind, müssen Sie das Element zwischenspeichern und dann dieselben Operationen wie zuvor ausführen.
console.profile (); var elem = $ ("# mainItem"); elem.hide (); // Irgendein Code elem.val ("Hello"); // More code elem.html ("Oh, hey da!"); // Noch mehr Code elem.show (); console.profileEnd ();
Wie aus den Ergebnissen hervorgeht, verkürzt das Zwischenspeichern oder Verketten die Ausführungszeit erheblich.
In meinem früheren Artikel wurde vorgeschlagen, nicht-traditionelle DOM-Manipulationen zu verwenden, was ein paar Flak von ein paar Leuten zog, bevor gezeigt wurde, dass der Leistungsanstieg sich wirklich lohnt. Wir werden es jetzt selbst testen.
Für den Test erstellen wir 50 li Elemente an, hängen sie an die aktuelle Liste an und legen fest, wie lange es dauert.
Wir werden zuerst die normale, ineffiziente Methode überprüfen. Wir fügen das Element grundsätzlich bei jeder Ausführung der Schleife an die Liste an.
console.profile (); var list = $ ("# someList"); für (var i = 0; i<50; i++) list.append('
Mal sehen, wie es gemacht hat, sollen wir?
Nun gehen wir einen etwas anderen Weg. Wir werden die erforderliche HTML-Zeichenfolge im Wesentlichen an eine Variable firs anhängen und das DOM dann nur einmal umfließen.
console.profile (); var list = $ ("# someList"); var items = ""; für (var i = 0; i<50; i++) items += '
Wie erwartet hat sich der Zeitaufwand erheblich verringert.
Wenn Sie jQuery als Ersatz für getElementById verwenden, aber niemals eine der bereitgestellten Methoden verwenden, dann machen Sie es falsch.
Wenn Sie die Dinge weiter ausführen möchten, fragen Sie sich, ob Sie wirklich ein neues jQuery-Objekt erstellen müssen, um auf ein Element zu zielen. Wenn Sie jQuery als Ersatz für document.getElementById verwenden, aber niemals eine der bereitgestellten Methoden verwenden, dann machen Sie es falsch. In diesem Fall können wir mit rohem JS davonkommen.
console.profile (); var list = document.getElementById ('someList'); var items = "; for (var i = 0; i<50; i++) items += '
Sie werden feststellen, dass der Unterschied in der Ausführungszeit zwischen dem optimierten und dem nicht optimierten Code im Bruchteil einer Millisekunde liegt. Dies liegt daran, dass unser Testdokument mit einer unglaublich geringen Anzahl von Knoten sehr klein ist. Wenn Sie anfangen, mit Websites auf Produktionsniveau zu arbeiten, die einige tausend Knoten enthalten, wird dies wirklich groß sein.
Beachten Sie auch, dass ich bei den meisten dieser Tests einfach auf die Elemente zugreife. Wenn Sie mit den richtigen Funktionen beginnen, wird das Delta in der Ausführungszeit größer.
Ich verstehe auch, dass dies nicht die wissenschaftlichste Methode ist, um die Leistung zu testen. Um jedoch ein allgemeines Gefühl dafür zu bekommen, wie sehr jede dieser Änderungen die Leistung beeinflusst, denke ich, dass dies ausreichend ist.
In den meisten Ihrer Web-Apps wird schließlich die Verbindungsgeschwindigkeit und Reaktionszeit des betreffenden Webservers eine größere Rolle für die Leistung Ihrer App spielen als die Änderungen im Code, die Sie vornehmen. Trotzdem ist dies immer noch eine wichtige Information, die Ihnen helfen wird, wenn Sie versuchen, so viel Leistung wie möglich aus Ihrem Code herauszuholen.
Und wir sind fertig. Ein paar Punkte, die Sie beachten sollten, wenn Sie versuchen, Ihren Code zu optimieren. Dies ist natürlich nicht die alles umfassende Liste von Optimierungen, und die Punkte treffen möglicherweise nicht unbedingt auf alle Situationen zu. In jedem Fall werde ich mir die Kommentare genau ansehen, um zu lesen, was Sie zu dem Thema sagen müssen. Irgendeinen Fehler, den Sie hier sehen? Schreib mir eine Zeile unten.
Fragen? Schöne Dinge zu sagen? Kritikpunkte Schlagen Sie den Kommentarbereich an und hinterlassen Sie einen Kommentar. Glückliche Kodierung!